Sep 16 2018
Sep 16

Privileged to be given the opportunity by organisers at Drupal Europe to share Peace Through Prosperity‘s journey with the Drupal community. Thank you!

This was the third rendition of this talk since 2015, and in this time our charity, our work, progress of our beneficiaries and our learnings from it have come a long way.

What started as a one way street for transfer of frameworks, tools and strategies from digital transformation to effect societal transformation has gone full circle over past couple of years. Eight years into the journey and am now cross-pollinating approaches and ideas from societal transformation back into my work as a digital transformation coach and consultant.

Suppose it was a matter of time when I started seeing patterns from marginalised individuals and communities back into the work place with disengaged teams and individuals! But that’s for another post!

As mentioned in my session there are two call to actions to further Peace Through Prosperity’s journey to continue and scale our work…

  1. We are looking to partner with organisations on their Corporate Social Responsibility(CSR) programs – kindly reach out to your organisation’s CSR people and suggest sponsoring Peace Through Prosperity just as DropSolid currently do! We are looking to raise €30k with which we’d be able to engage with 800 micro-entrepreneurs in a 12 month period!
  2. Steal our stuff – connect us with your friends, customers and acquaintances in the charity sector, we would like for them to steal our open source products and programs, incorporate them in their existing work and we will support them in the task! it’s free!

My session at Drupal Europe coincided with Peace Through Prosperity running a mini-MBA for our third all female cohort in Lyari, Karachi! here’s 35+ micro-entrepreneurs from a marginalised community in Karachi stepping out of their comfort zone and graduating from the program! Well done ladies!

Interested to learn more? would you like to get involved? Cool! get in touch, you know how to find me!

And lastly I’d like to add a special mention for Druid from Finland! these folks brought along SWAG for kids! their T-shirts are an absolute hit with mine! #Thankyou

#DrupalEurope #Agile #Transformation #Society #Entrepreneurs #InternationalDevelopment

Apr 06 2018
Apr 06

This is the second rendition of this topic within the Drupal Community, the first time I shared my experiences and journey in this context was at Drupal Camp Sofia, in Bulgaria in 2015. In many respects this is quite a circle for me, I have fond memories of attending a Drupal meet-up in Utrecht (long way from home in Kent!) in 2012, receiving a very warm welcome by the local community at OneShoe’s very eclectic offices and meeting the personality that is Michel.

Fast forward six odd years and am stoked to be going back to Utrecht to share with a community that has been a source of inspiration for what we do at Peace Through Prosperity! I hope our work at Peace Through Prosperity serves to be a source of inspiration for my fellow Drupal community members and friends.

The session at DrupalJam 2018 has been recorded and shall add a link to the video as and when it is up. It also happens to be my eldest daughter Alvera’s second Drupal community event, first DrupalJam!! Well done! #SuperProudDad And last but not the least thank you to the DrupalJam team, to the attendees and my Acquia colleagues  Nicky Rutten and Maartje Sampers their time.

…………

Lastly, If you got value from what I have shared please consider giving back by contributing to @BringPTP, you can followbroadcast or donate.

Peace Through Prosperity (PTP) works to improve the environment for peacebuilding by nurturing prosperity in conflict affected communities. We work to alleviate poverty and secure livelihoods through empowering micro-entrepreneurs with knowledge, skills and increasing their access to income and opportunities. We support small businesses, owned/managed by vulnerable and marginalised individuals/groups in society.

Mar 11 2017
Mar 11

Drupal 8

Drupal 8

I carried out a empathy mapping exercise at Drupal Camp London 2017 to capture the community’s perspective towards Drupal 8

The community perspective from Drupal Camp London towards Drupal 8:

Drupal 8 Empathy mapping the community's perspective 2017

Drupal 8 Empathy mapping the community's perspective 2017

I would encourage you to download the template, use it capture the community perspectives at your own Camps and meetups. The template can be downloaded here, and is best printed out as an A1 poster. 

Additionally please use the hashtag #D8Empathy to broadcast your findings. So that we can compare maps across camps to improve our understanding of the community and Drupal 8’s impact on it.

……

Lastly, If you got value from what I have shared please consider giving back by contributing towardsPeace Through Prosperity, you can follow, broadcast or donate.

Peace Through Prosperity improves the local/domestic environment for peace by nurturing prosperity in conflict affected geographies. We work to alleviate poverty, prevent radicalisation by empowering micro-entrepreneurs from marginalised communities. 

Peace Through Prosperity is innovating social transformation design and delivery using Agile frameworks to create and deliver low cost, high impact social development programs in ‘at risk’ communities.

Mar 07 2017
Mar 07

First and foremost thank you to all who made the time to attend my session on Empathy Driven Content Strategy at Drupal Camp London 2017. Thank you for sharing your time and perspectives.

This session was an evolution of two previous sessions:

There is a difference between walking in someone else’s footsteps and walking in their shoes!

‘Empathy Driven Content Strategy’ explores the transformation in content consumption, purpose, generation and how it impacts us. Looking at how empathy, touch points, sentiment analysis and emotional intelligence can be harnessed to create richer, more personalized experiences for people. With the purpose of motivating others to share the journey with us with content that is pertinent to and addresses their needs over the course of the journey.

We have seen how, over the past year empathy driven content, the use of sentiment analysis and knowing which touchpoint to invest in has played its role in both Brexit and the Trump campaigns. There are lessons behind their success for all regardless of which side of the campaign divide we may sit on.

As for getting started with Empathy maps, you can download examples and a blank canvas from the resources section below. Bear in mind the key takeaway is to ‘talk to people’ treat them as people first (customers later), to engage for the sake of understanding and keep our instinct to react in check… only when we understand can we respond.

Resources mentioned during the session:

Sentiment Analysis
Further reading

…………………..

Lastly, If you got value from what I have shared please consider giving back by contributing to @BringPTP, you can follow, broadcast or donate.

Peace Through Prosperity (PTP) improves the local/domestic environment for peace by nurturing prosperity in conflict affected geographies. We work to alleviate poverty, prevent radicalisation through empowering micro-entrepreneurs with knowledge, skills, ability and increasing their access to income and opportunities. We support small businesses, owned/managed by vulnerable and marginalised individuals/groups in society.

Peace Through Prosperity (PTP) is innovating social transformation design and delivery by using Agile frameworks to create and deliver low cost, immediate and lasting impact social development programs in ‘at risk’ communities.

Feb 12 2017
Feb 12

This is first of a series of blogs to support traditional project managers I am coaching. To help get their bearings in deep and murky waters of Agile projects and Scrum teams.

Before the scrum purists amongst you vehemently shake your heads or berate me on the title, consider being pragmatic. In the Professional Services world there is always a project manager to manage complexity and facilitate the Scrum team(s). My remit is to facilitate and empower the role to help the team, business and customers succeed, rather than debate its applicability and existence.

“Obey the principles without being bound by them.”
– Bruce Lee

I’ll be deep diving into a PM’s role in context to specific Scrum ceremonies in upcoming posts, however its seems apt to start with some health warnings.

Toxic Behaviour for a Scrum team

Toxic Behaviour for a Scrum team

A) This is not a guide for you to try and replace the Scrum master (you cannot) or the product owner (you cannot), or both! (you cannot). Nor is it a reference for you to justify imposing your will on the team (you cannot). It’s a guide to enable you to add ‘value’ to the ‘Scrum team’ and fulfill your purpose of managing risk on complex engagements.

B) Please don’t try to fake it till you make it! you will be caught out and the team will loose respect for you. if you don’t know, embrace not knowing and work to change that. Learn, up-skill, ask for help, do a pre-project retrospective on your own experience and discuss it with your Scrum master and/or Agile coach (if you have one). If you go in waving your strengths and weaknesses we will respect you for your courage and openness… they are part of our value system

C) Own your failures and reflect on them with the scrum master and/or an Agile coach. Don’t look for patsies, the team
will see through it and you will be called out on it. If you are failing, own it, be courageous and open, respect the knowledge and skills your Scrum team has (and you don’t) and in turn you will earn their respect. If you blame someone else for your shortcomings so that you can hide behind them you do not have the DNA to be in an agile environment. 

Agility, Scrum it’s a culture thing!

Agile Culture

Agile Culture

In order for you (a PM) to facilitate a Scrum team (yes your role is one of facilitation only) it is essential that you understand and embrace an agile culture, not just follow parts of a framework (Scrum). Toe-dipping is not going to work, you’re either committed or not.. its time to quit being a chicken and start living like a Pig

……………………

Lastly, If you got value from what I have shared please consider giving back by contributing to @BringPTP, you can follow, broadcast or donate.

Peace Through Prosperity (PTP) works to improve the environment for peacebuilding by nurturing prosperity in conflict affected communities. We work to alleviate poverty and secure livelihoods through empowering micro-entrepreneurs with knowledge, skills and increasing their access to income and opportunities. We support small businesses, owned/managed by vulnerable and marginalised individuals/groups in society.

Nov 17 2016
Nov 17

This latest release for [RNG](RNG brings two major features: The ability for anonymous users to register for events. And the ability to create, and associate non-users with events.

RNG is an event management module for Drupal 8 created in the spirit of Entity Registration (Drupal 7) and Signup (Drupal 6). Users can create registrations for events, and event managers can manage these registrations.

Note: This post discusses updates to the RNG project which are available in a beta release. See this issue for how to get RNG 1.3 beta.

The event registration form has been reworked into a re-usable Drupal element, whilst making heavy use of AJAX. The registrant selector now accepts multiple registrants. Registrants can also be modified after the registration is created.

*Associate multiple registrants with a registration.* *Create new registrants within the registration form.* *Modify the meta registrant form within the registration form.*

Access control has been reworked to permit anonymous users to register for events.

RNG requires that all registrants for a registration are a Drupal entity. Since anonymous users do not correspond to a user entity, the RNG Contact project provides a way to create non-user registants in a similar fashion to how contacts work on your phone.

See main RNG Contact article: RNG Contact: Anonymous registrants for RNG.

  • Registrant entities now have bundles
  • Added registrant type configuration entity
  • Added control over which identity types can be referenced or created within each event type.
  • Added ability to specify minimum and maximum registrants per registration.
  • Added an interface to view and add RNG related fields.
  • Event settings pages now use the admin theme.
  • And many other behind the scene changes.

Cover photo: B&W Crowd by whoohoo120. License CC BY 2.0

Jul 30 2016
Jul 30
‘I want to create a practical guide for product owners to facilitate them in writing acceptance criteria for user stories so that their output is of value to the scrum team’

You’ll find pages after pages describing what an acceptance criteria is and how to write a good one, what it should include or not, however this post takes a practical approach for Product Owners to follow. You’ll find post after post describing how product owners ought to use Gherkin script to develop/write an acceptance criteria, which in my opinion is not a practical approach, there are a few things wrong with that approach, a few come to mind right now:

a) not many product owners know Gherkin script and it’s unreasonable to expect them to adopt it when the team itself is better placed to translate their acceptance criteria into Gherkin. Doing so has its merits, the team has to analyse the acceptance criteria and develop Gherkin based test scripts from it, furthermore the product owner’s velocity for producing acceptance criteria is hugely improved as he/she is defining the fitness for purpose in a natural language.

b) calling out a product owner to write acceptance criteria in Gherkin or in a scripted fashion is prescriptive and goes against an agile approach, which is based on practicality and common sense. The Scrum master and team’s role is to facilitate the process, don’t assume your product owner can script!

Now that my preferred approach is set, lets dive into it:

For the newbies; acceptance criteria defines the intent of a user story, and is used to confirm if the user story is fit for purpose; the user story does what was intended, if so then the user story is complete. If you’re new to user stories please go here first.

Acceptance criteria must be developed by the product owner, it can be facilitated by the Scrum team but it’s responsibility must rest with the product owner.

The Scrum team’s expectations of the product owner to develop acceptance criteria must be realistic.

Things an acceptance criteria must cover (where relevant); usability, exceptions, desired output if the US is data driven, error handling, UX requirements, validations, any security and performance requirements as well as the function it’s seeking to validate.

Furthermore where applicable insist that the PO adds a wireframe or screen grab of the desired outcome for the user story. For those of you interested in a working example, there is one detailed out at the end of this post.

For those wondering when an AC needs to be in place…. It’s part of your *DoR (Definition of Ready) for the user story itself, your user story is not ready for technical decomposition or estimation without an acceptance criteria. 

For product owners looking for guidance to write acceptance criteria, a starter for 10:
  • Focus on the what and not the how – the team is not looking for a ‘solution’ from you as the product owner, just the ‘what’ is it that you are asking of the user story.
  • Keep the end user (and user acceptance testing) firmly in focus, it’s their point of view and value you are representing.
  • Develop acceptance criteria as a set of statements, each clearly stating a pass/fail outcome.
  • Specify both functional and non-functional requirements.
  • What are your security and performance requirements, need it be real time data display? Is the data sensitive?
  • Start with a sketch of what you are asking for, remember a picture paints a thousand words! 
  • There is no such thing as partial acceptance: either the acceptance criteria is met or it is not.
  • What is your user story? Think about what your want is? Can it be visually displayed? Is it related to display of data? Sketch out the different data entities (columns) you want to see, do you need to sort the display/view of data? Think it through in detail.
  • Is it a form to capture data? What data entities do you want captured? In what format? Think about what you don’t want in those fields (restricting input types), how would you validate the entries, what are the validation business rules?

This is a starting point for you and not a comprehensive list of do’s and don’ts, be pragmatic, and discuss the acceptance criteria with the Scrum team and your end user representatives; ‘conversation’ is a critical component of a user story and one that helps product owners bottom out the details of a user story’s acceptance criteria.

Your acceptance criteria must be acceptable to the Scrum team, if not then your acceptance criteria itself is not fit for purpose .

A tale from the trench

Our product owner’s requirement early on in the discovery stage was: ‘I want a login page to authenticate users on the site.’

So our user story would have been a simple one: ‘As a user I want to sign in to the site from a login page so that users can be authenticated.’

Then we began the deep dive conversation with our product owner; so what’s your acceptance criteria for the requirement?

and what we got was:

  • From on any page be able to access the login page via a sign in link.
  • On the site when I click the ‘sign-in’ link, I am re-directed to the login page where I can enter my email and password for authentication 
  • Upon successful login, I am re-directed to the homepage.
  • On the homepage my first name is displayed in the upper right hand corner along with the date and time of my last login.
  • If I enter an incorrect username and or password I should see an appropriate error message indicating my credentials are incorrect.
  • I should be able to retry authenticating myself three times before I am locked out of my account and must reset my password to unlock my account
  • My password needs to follow the company password policy for secure passwords
  • I must also see a link which allows me to re-set my password.
  • I must also see a link which allows me to register is i am a new user.

Can you spot the increased/emergent scope creep in the acceptance criteria as detailed by the product owner above?

Having seen the scope balloon we asked our product owner to sketch a wireframe for the login page, we were convinced there will be more that will emerge from a wireframe.

The wireframe sketched out by our product owner:

Login page wireframe

Login page wireframe

 

Can you spot further scope that has emerged from the wireframe? How often has the above played out for you and your team? 

We discussed the need for the additional user stories to capture the emergent scope  as well as the necessity of keeping the acceptance criteria for the original user story narrow to the user story itself. The conversation helped us identify additional user stories we needed to capture.

Having been through the exercise/discussions our product owner revised the acceptance criteria and the package looked like:

The User Story:

‘As a user I want to sign in to the site from a login page so that users can be authenticated.’

Its Acceptance Criteria:

  • On the sign-in page I can enter my email address and password and submit it for authentication.
  • My password needs to follow the company password policy for secure passwords
  • Upon successful login, I am re-directed to the homepage.
  • If I enter an incorrect username and or password I should see an appropriate error message indicating my credentials are incorrect.
  • I should be able to retry authenticating myself three times before I am locked out of my account and must reset my password to unlock my account.
  • I must also see a link which allows me to re-set my password.
  • I must also see a link which allows me to register is I am a new user.
  • I must see a CAPTCHA to protects the site against bots

The above user story and its acceptance criteria is independent, negotiable, valuable, estimable, small and testable within a single sprint, it is a user story and not an Epic that our product owner’s wireframe represented.

“Acceptance Criteria should not go beyond the scope of the user story, if so then additional user stories need to be captured that define the feature ‘wants’.” Well thought out acceptance criteria help us better understand the original scope, the emergent scope and create a contract with the product owner on the user story’s completeness and acceptability. * Thank you B for pointing out the typo. ……………..

Peace Through Prosperity (PTP) improves the local/domestic environment for peace by nurturing prosperity in conflict affected geographies. PTP alleviates poverty, prevents radicalisation through empowering micro-entrepreneurs with knowledge, skills, ability and increasing their access to income and opportunities. PTP supports small businesses, owned/managed by vulnerable and marginalised individuals/groups in society.

PTP is innovating social transformation program design and delivery by using Agile frameworks to create and deliver low cost, immediate and lasting impact social development programs in ‘at risk’ communities.

May 18 2016
May 18
teaser image for blog post

Members of the British Council Digital team were delighted to receive the RITA2016 award last Thursday for the huge change in IT cloud infrastructure that Ixis delivered in the summer of 2015.

The award for "Infrastructure as an Enabler" reflected the innovative change in the way the British Council undertook their hosting requirement for the initial 120 sites operating in over 100 countries across the globe and delivering a clear business benefit. Moving away from dedicated infrastructure to virtual containers provided the ability to tightly control and guarantee server resources to an individual site and a quick and easy way to duplicate an environment for QA, testing, staging and feature branch development.

Ixis partnered with Drupal container expert Platform.sh to provide the underlying infrastructure and API. We'll publish further detail on our integration as a case study.

Congratulations also go another of our clients: Westminster City Council, for their award and further two highly commended positions in this years awards.

Photo courtesy of Chaudhry Javed Iqbal on Twitter.

May 18 2016
May 18
teaser image for blog post

In this blog post I'll discuss some methods of ensuring that your software is kept up to date, and some recent examples of why you should consider security to be among your top priorities instead of viewing it as an inconvenience or hassle.

Critics often attack the stability and security of Open Source due to the frequent releases and updates as projects evolve through constant contributions to their code from the community. They claim that open source requires too many patches to stay secure, and too much maintenance as a result.

This is easily countered with the explanation that by having so many individuals working with the source code of these projects, and so many eyes on them, potential vulnerabilities and bugs are uncovered much faster than with programs built on proprietary code. It is difficult for maintainers to ignore or delay the release of updates and patches with so much public pressure and visibility, and this should be seen as a positive thing.

The reality is that achieving a secure open source infrastructure and application environment requires much the same approach as with commercial software. The same principles apply, with only the implementation details differing. The most prominent difference is the transparency that exists with open source software.

Making Headlines

Open Source software often makes headlines when it is blamed for security breaches or data loss. The most recent high profile example would be the Mossack Fonseca “Panama Papers” breach, which was blamed on either WordPress or Drupal. It would be more accurate to blame the firm itself for having poor security practices, including severely outdated software throughout the company and a lack of even basic encryption.

Mossack Fonseca were using an outdated version of Drupal: 7.23. This version was released on 8 Aug 2013, almost 3 years ago as of the time of writing. That version has at least 25 known vulnerabilities. Several of these are incredibly serious, and were responsible for the infamous “Drupalgeddon” event which led to many sites being remotely exploited. Drupal.org warned users that “anyone running anything below version 7.32 within seven hours of its release should have assumed they’d been hacked”.

Protection by Automation

Probably the most effective way to keep your software updated is to automate and enforce the process. Don’t leave it in the hands of users or clients to apply or approve updates. The complexity of this will vary depending on what you need to update, and how, but it can often be as simple as enabling the built-in automatic updates that your software may already provide, or scheduling a daily command to apply any outstanding updates.

Once you've got it automated (the easy part) you will want to think about testing these changes before they hit production systems. Depending on the impact of the security exploits that you're patching, it may be more important to install updates even without complete testing; a broken site is often better than a vulnerable site! You may not have an automated way of testing every payment permutation on a large e-commerce site, for example, but that should not dissuade you from applying a critical update that exposes credit card data. Just be sure you aren't using this rationale as an excuse to avoid implementing automated testing.

The simple way

As a very common example of how simple the application of high priority updates can be, most Linux distributions will have a tried and tested method of automatically deploying security updates through their package management systems. For example, Ubuntu/Debian have the unattended-upgrades package, and Redhat-based systems have yum-cron. At the very least you will be able to schedule the system’s package manager to perform nightly updates yourself. This will cover the OS itself as well as any officially supported software that you have installed through the package manager. This means that you probably already have a reliable method of updating 95% of the open source software that you're using with minimal effort, and potentially any third-party software if you're installing from a compatible software repository. Consult the documentation for your Linux distro (or Google!) to find out how to enable this, and you can ensure that you are applying updates as soon as they are made available.

The complex way

For larger or more complex infrastructure where you may be using configuration management software (such as Ansible, Chef, or Puppet) to enforce state and install packages, you have more options. Config management software will allow you to apply updates to your test systems first, and report back on any immediate issues applying these updates. If a service fails to restart, a service does not respond on the expected port after the upgrade, or anything goes wrong, this should be enough to stop these changes reaching production until the situation is resolved. This is the same process that you should already be following for all config changes or package upgrades, so no special measures should be necessary.

The decision to make security updates a separate scheduled task, or to implement them directly in your config management process will depend on the implementation, and it would be impossible to cover every possible method here.

Risk Management

Automatically upgrading software packages on production systems is not without risks. Many of these can be mitigated with a good workflow for applying changes (of any kind) to your servers, and confidence can be added with automated testing.

Risks

  • You need to have backups of your configuration files, or be enforcing them with config management software. You may lose custom configuration files if they are not flagged correctly in the package, or the package manager does not behave how you expect when updating the software.
  • Changes to base packages like openssl, the kernel, or system libraries can have an unexpected effect on many other packages.
  • There may be bugs or regressions in the new version. Performance may be degraded.
  • Automatic updates may not complete the entire process needed to make the system secure. For example, a kernel update will generally require a reboot, or multiple services may need to be restarted. If this does not happen as part of the process, you may still be running unsafe versions of the software despite installing upgrades.

Reasons to apply updates automatically

  • The server is not critical and occasional unplanned outages are acceptable.
  • You are unlikely to apply updates manually to this server.
  • You have a way to recover the machine if remote access via SSH becomes unavailable.
  • You have full backups of any data on the machine, or no important data is stored on it.

Reasons to NOT apply updates automatically

  • The server provides a critical service and has no failover in place, and you cannot risk unplanned outages.
  • You have custom software installed manually, or complex version dependencies that may be broken during upgrades. This includes custom kernels or kernel modules.
  • You need to follow a strict change control process on this environment.

Reboot Often

Most update systems will also be able to automatically reboot for you if this is required (such as a kernel update), and you should not be afraid of this or delay it unless you're running a critical system. If you are running a critical system, you should already have a method of hot-patching the affected systems, performing rolling/staggered reboots behind a load-balancer, or some other cloud wizardry that does not interrupt service.

Decide on a maintenance window and schedule your update system to use it whenever a reboot is required. Have monitoring in place to alert you in the event of failures, and schedule reboots within business hours wherever possible.

Drupal and Other Web-based Applications

Most web-based CMS software such as Drupal and Wordpress offer automated updates, or at least notifications. Drupal security updates for both core and contributed modules can be applied by Drush, which can in turn be scheduled easily using cron or a task-runner like Jenkins. This may not be a solution if you follow anything but the most basic of deployment workflows and/or rely on a version control system such as Git for your development (which is where these updates should go, not direct to the web server). Having your production site automatically update itself will mean that it no longer matches what you deployed, nor what is in your version control repository, and it will be bypassing any CI/testing that you have in place. It is still an option worth considering if you lack all of these things or just want to guarantee that your public-facing site is getting patches as a priority over all else.

You could make this approach work by serving the Git repo as the document root, updating Drupal automatically (using Drush in 'security only' upgrade mode on cron), then committing those changes (which should not conflict with your custom code/modules) back to the repo. Not ideal, but better than having exploitable security holes on your live servers.

If your Linux distribution (or the CMS maintainers themselves) provide the web-based software as a package, and security updates are applied to it regularly, you may even consider using their version of the application. You can treat Drupal as just another piece of software in the stack, and the only thing that you're committing to version control and deploying to servers is any custom modules to be layered on top of the (presumably) secure version provided as part of the OS.

Some options that may fit better into the common CI/Git workflows might be:

  • Detect, apply, and test security patches off-site on a dedicated server or container. If successful, commit them back to version control to your dev/integration branch.
  • Check for security updates as part of your CI system. Apply, test and merge any updates into your integration branch.

Third-party Drupal Modules (contrib)

Due to the nature of contrib Drupal modules (ie, those provided by the community) it can be difficult to update them without also bringing in other changes, such as new features (and bugs!) that the author may have introduced since the version you are currently running. Best practice would be to try to keep all of the contrib that the site uses up to date where possible, and to treat this with the same care and testing as you would updates to Drupal itself. Contrib modules often receive important bug fixes and performance improvements that you may be missing out on if you only ever update in the event of a security announcements.

Summary

  • Ensure that updates are coming from a trusted and secure (SSL) source, such as your Linux distribution's packaging repositories or the official Git repositories for your software.
  • If you do not trust the security updates enough to apply them automatically, you should probably not be using the software in the first place.
  • Ensure that you are alerted in the event of any failures in your automation.
  • Subscribe to relevant security mailing lists, RSS feeds, and user groups for your software.
  • Prove to yourself and your customers that your update method is reliable.
  • Do not allow your users, client, or boss to postpone or delay security updates without an incredibly good reason.

You are putting your faith in the maintainer's' ability to provide timely updates that will not break your systems when applied. This is a risk you will have to take if you automate the process, but it can be mitigated through automated or manual testing.

Leave It All To Somebody Else

If all this feels like too much responsibility and hard work then it’s something Ixis have many years of experience in. We have dedicated infrastructure and application support teams to keep your systems secure and updated. Get in touch to see how we can ensure you're secure now and in the future whilst enjoying the use and benefits of open source software.

Apr 25 2016
Apr 25
teaser image for blog post

Over the last couple of years, we have been using Codeception at Ixis for running automated acceptance tests during development work. Over this time we attempted to distil some of the ideas and abstract custom code into Codeception modules, which are all available on GitHub.

Adopting Codeception for automated acceptance testing has been quite the learning process: getting used to the Codeception system, best practices and underlying code; facing challenges when writing tests for unusual or difficult situations; moving from the cURL-based PhpBrowser to the more advanced and complex WebDriver; problems with underlying components such as Selenium and PhantomJS; lack of integration with Drupal... phew! And that's not before we've considered processes, methods and best practices for running automating testing itself!

The latter, however, is a story for perhaps another time. This post summarises the Codeception modules we've worked on, why they might be useful and some lessons learned.

Drupal Content Type Registry

Drupal Content Type Registry is a module to provide a set of classes that encapsulate Drupal content types. This makes it much easier to quickly test standard Drupal functionality relating to content types, taking into account how they exist on your site. It enables testing of things such as the content types admin page, the 'manage fields' page for each content type, and provides createNode() and deleteNode() methods that can be used to quickly create test nodes where you can provide the test data using specific values, random values, or a range of values where one is picked at random.

Once enabled, a contentTypes.yml file should be created which defines:

  • GlobalFields - fields that will be used across all of the content types on the site. This is useful for things like title and body fields, to save you having to redefine the exact same field on every content type.
  • ContentTypes - content types on the site and the fields they have (global or otherwise).

Here's the example from the README:

GlobalFields:
    body:
        machineName:    body
        label:          Body
        type:           Long text and summary
        selector:       "#edit-body-und-0-value"
        widget:         Text area with a summary
        required:       true
    title:
        machineName:    title
        label:          Title
        type:           Node module element
        selector:       "#edit-title"
ContentTypes:
    news:
        humanName:    News
        machineName:  news
        fields:
            globals:
                - title
                - body
            field_image:
                machineName:    field_image
                label:          Image
                type:           Image
                selector:       "#edit-field-image"
                widget:         Media file selector
                required:       true
                testData:       "image1.png"
            field_icon:
                machineName:    field_icon
                label:          Icon
                type:           Text
                selector:       "#edit-field-icon"
                widget:         Text field
                skipRoles:
                    - editor
                    - publisher
                testData:
                    - smiley
                    - grumpy
                    - happy
                    - wacky
                preSteps:
                    - ["click", ["#button"]]
                    - ["fillField", ["#the-field", "the-value"]]
                postSteps:
                    - ["waitForJs", ["return jQuery.active == 0;"]]
        submit: "#edit-submit-me-please"

The definition of fields comprises the machine name, label, field type, widget and CSS ID or selector used when filling in node edit forms. Similarly, the definition of content types comprises the machine name, human-readable name and a list of field definitions. The module also provides a set of classes representing most field widgets provided by Drupal 7 core.

There are other features too, such as: preSteps and postSteps, which allow optional steps to run before and after filling the field; testData, which allows specific test data (literals or random text) to be used for each field; skippedRoles, which skips certain fields for specific user roles when creating nodes; and "Extras", which simulate the user clicking things on the node edit form that are not actually fields, like set the sticky status or the publication status of a node. For more detailed information on the module's configuration, see the README file.

This module (in combination with Drupal User Registry) also provides enough to create close to generic tests that will check your Drupal 7 site for all expected content types and fields. See this example Gist.

Credit must go to Chris Cohen for his original work on the Content Type Registry.

Drupal Drush

Drupal Drush allows the running of Drush commands in acceptance tests. It also allows the use of the following statements in tests:

// Execute "drush cc all"
$I->getDrush("cc", array("all"))->mustRun();

The getDrush() method returns and instance of Symfony\Component\Process\Process so you can read stdout, get the exit code, etc. The ->mustRun() method is useful as a Symfony\Component\Process\Exception\ProcessFailedException exception will be thrown if the command fails, meaning your test will automatically fail.

Drupal Mail System

Drupal Mail System allows the testing of the Drupal mail system.

// Test to see expected number of emails sent.
$I->seeNumberOfEmailsSent(1);
 
// Clear emails from queue.
$I->clearSentEmails();
 
// Check email fields contains text
$I->seeSentEmail(array(
    "body" => "body contains this text",
    "subject" => "subject contains this text",
));

Relies on TestingMailSystem class which stores the emails in a Drupal system variable.

Drupal Pages

Drupal Pages is a dependency of some other modules listed here and contains several PageObjects for "generic" Drupal 7 pages, based on "vanilla Drupal 7' and the default Bartik front-end or Seven administration themes. These PageObject classes can be extended to override any static properties as required for the site being tested.

Drupal User Registry

Drupal User Registry is a Codeception module for managing test users when running acceptance tests with Codeception. Once configured, it can automatically create and delete test Drupal users at the beginning and end of a test suite run. These users can then be used during acceptance tests to login and test elements of the project specific to that role.

The module is configured in the suite configuration:

class_name: AcceptanceTester
modules:
    enabled:
        - PhpBrowser
        - DrupalUserRegistry
    config:
        PhpBrowser:
            url: 'http://localhost/myapp/'
        DrupalUserRegistry:
            defaultPass: "foobar"
            users:
                administrator:
                    name: administrator
                    email: admin@example.com
                    pass: "foo%^&&"
                    roles: [ administrator, editor ]
                    root: true
                editor:
                    name: editor
                    email: editor@example.com
                    roles: [ editor, sub-editor ]
                "sub editor":
                    name: "sub editor"
                    email: "[email protected]"
                    roles: [ sub-editor ]
                authenticated:
                    name: authenticated
                    email: authenticated@example.com
                    roles: [ "authenticated user" ]
            create: true
            delete: true
            drush-alias: '@mysite.local'
  • defaultPass - use this password for all created user accounts, unless they have one individually specified.
  • users - a list of test user accounts to create, complete with username. email, password and a list of roles.
  • create and delete - whether to create and delete users at the start and end of a run.
  • drush-alias - the Drush alias to use when managing users via DrushTestUserManager.

Once configured, the module also allows the use of the following statements in tests:

// Returns a DrupalTestUser object representing the test user available for
// this role.
$user = $I->getUserByRole($roleName);
 
// Returns a DrupalTestUser object representing the test user available for
// exactly these roles.
$user = $I->getUserByRole([$roleName1, $roleName2]);
 
// Returns a DrupalTestUser object representing the user, or false if no users
// were found. Note this will only return a user defined and managed by this
// module, it will not return information about arbitrary accounts on the site
// being tested.
$user = $I->getUser($userName);
 
// Returns an indexed array of configured roles, for example:
//   array(
//     0 => 'administrator',
//     1 => 'editor',
//     2 => ...
//   );
$roles = $I->getRoles();
 
// Returns a DrupalTestUser object representing the "root" user (account with
// uid 1), if credentials are configured:
$rootUser = $I->getRootUser();

This module is used in any acceptance test suite we create in order to test specific elements where being logged in as a user with specific roles is necessary. However, there are some limitations and improvements that could be made.

The user registry can be used in combination with codeception Step Objects and Drupal Pages to provide login and logout functions to enable testing as an authenticated user. For example:
    $ php codecept.phar generate:stepobject acceptance AuthenticatedSteps
    class AuthenticatedSteps extends \AcceptanceTester
    {
        /**
         * Log in.
         *
         * @param DrupalTestUser $person
         *   The Drupal Person to log in.
         */
        public function login(DrupalTestUser $person)
        {
            $I = $this;
 
            $I->amOnPage(UserAccountPage::route('login'));
            $I->expectTo('not be redirected due to already being logged in');
            $I->seeCurrentUrlEquals('/' . UserAccountPage::route('login'));
 
            $I->expectTo('see various elements of the login page');
            $I->seeElement(UserAccountPage::$loginFormUsernameSelector);
            $I->seeElement(UserAccountPage::$loginFormPasswordSelector);
            $I->seeElement(UserAccountPage::$loginFormSubmitSelector);
 
            $I->amGoingTo('fill in the login form');
            $I->fillField(UserAccountPage::$loginFormUsernameSelector, $person->name);
            $I->fillField(UserAccountPage::$loginFormPasswordSelector, $person->pass);
            $I->click(UserAccountPage::$loginFormSubmitSelector);
 
            $I->expectTo('log in successfully');
            $I->dontSee(UserAccountPage::$loginFormCredentialsErrorMessage, Page::$drupalErrorMessageSelector);
        }
 
        /**
         * Log out.
         */
        public function logout()
        {
            $I = $this;
 
            $I->amGoingTo('log out');
            $I->amOnPage(UserAccountPage::route('logout'));
            $I->expectTo('be redirected to the front page');
            $I->seeCurrentUrlEquals('/');
        }
    }
Then in a test:
    /**
     * Test pages.
     *
     * @guy AcceptanceTester\AuthenticatedSteps
     */
    class ThePagesCest
    {
        /**
         * Test the page as an authenticated user.
         *
         * @param AuthenticatedSteps $I
         */
        public function testThePage(AuthenticatedSteps $I)
        {
            $I->login($I->getRootUser());
            // ...
            $I->logout();
        }
    }

There's potential for integrating the login(), logout() and other related functionality into the Drupal User Registry module itself, but still allow the test suite author to override or specify these procedures themselves.

Drupal Variable

Drupal Variable allows us to test Drupal system variables, for example:

// Assert that the target site has variable "clean_url" set to 1
$I->seeVariable("clean_url", 1);
 
// Set a variable.
$I->haveVariable("clean_url", 0);
 
// Delete a variable.
$I->dontHaveVariable("clean_url");
 
// Retrieve a variable value.
$value = $I->getVariable("clean_url");

This module was the key to working out different "connections" to Drupal itself. Previously, we were restricted by the assumption that everything needed to be done via the browser in acceptance testing (see the lessons learned around creating test content via the test browser, in Drupal Content Type Registry above).

Drupal Variable can connect to a Drupal site using one of three methods:

  • Bootstrapped - if the site is accessible on a locally mounted file system, fully bootstrapping the site is possible. In this case we use the Codeception\Module\Drupal\Variable\VariableStorage\Bootstrapped class and ensure we set the drupal_root configuration setting.
  • Direct connection - if the site is remote but we have access via an open MySQL connection, we use the Codeception\Module\Drupal\Variable\VariableStorage\DirectConnection class and set a dsn, user and password.
  • Drush - if the site is remote but access via a Drush alias is available, we use the Codeception\Module\Drupal\Variable\VariableStorage\Drush class and ensure we set the drush_alias setting in the module's configuration.

In review

Problems with creating test content in the browser

Creating lots of test content in the browser with Drupal Content Type Registry has proved problematic in places and in hindsight not the best way to achieve our goal. Many of our development projects and supported sites have additional elements that make things that little more difficult too, such as alternative publishing workflows with Workbench or WYSIWYG editing and media management with CKEditor and the Media suite of modules.

Whilst these are problems that must be tackled when explicitly testing the UI and user flow to verify a particular feature, it's not necessary to effectively repeatedly run this test in order to set up test data and content. Not only is it in places complex, but running a full suite (in multiple environments, i.e. in different browsers) is slow and a lot of that time is (obvious facepalm incoming) setting up test data.

Once we had a more 'useful' connection to Drupal with Drush, database or a fully bootstrapped connection as implemented in the Drupal Variable module, it became clear that there could be a better (or at least faster) way of setting up test content. We're not 100% what this will involve yet, perhaps custom code, or integration with modules such as Migrate or Node export.

Refactoring and relating the modules

Most of these module sprang from solving different problems whilst testing different projects. Whilst we have one or two suites using all if not most of them, the modules function together but may benefit from refactoring any shared code. For example, Drupal User Registry will currently check for, create and delete test users using Drush and aliases and the original intention was to have other ways of doing so via other connections. As mentioned above, Drupal Variable implements a different method but already has three types of connection, including Drush, which Drupal User Registry could utilise.

Behat?

Fairly recently Codeception introduced Gherkin and natural language features which is up there at the top of a list of advantages that Behat may have over Codeception - second only to it's much more extensive integration with Drupal, of course! Behat is being considered as an alternative or supplemental method for testing our Drupal sites.

Mar 07 2016
Mar 07
teaser image for blog post

In learning about custom Drupal 8 module development, I found plenty of very simple field module examples, but none that covered how to store more than one value in a field and still have it work properly, so it's time to fix that.

To save you typing or copy and pasting things around all the code in this post is available on Github at https://github.com/ixis/dicefield

Concepts

There are three main elements to define when creating a field type:

  • The field base is the definition of the field itself and contains things like what properties it should have.
  • The field widget defines the form field that is used to put data into your field, what its rules are and how those data are manipulated and stored in the field.
  • The field formatter is how the field will be displayed to the end user and what options are configurable to customise that display.

So far, so familiar if you've ever worked with Drupal 7 fields, and this is like so much of Drupal 8: on the surface, to the end user, it's very similar, but behind the scenes, it's a whole new world.

Use case

To create a (probably quite limited-use, in all honesty) real-world example, I decided to take on the challenge of creating a field to represent dice notation. For example, if you see 1d6 you would grab a single six-sided die and roll it. If you see 3d6-2, you would roll 3 six-sided dice and subtract 2 from the result.

There are three components here:

  • The number of dice
  • The number of sides on each die
  • The modifier: the part that is added or subtracted at the end

Although in practice you could store the whole thing as one big string, and it would be a walk in the park to set up, you would lose some of the more useful functionality, such as search indexing and sorting at a database level. Suppose you wanted to create a view that filtered only field values that involved rolling 5 dice. With a multi-value field such as the one we're creating, it's simple to do. If you store everything as one big string, it involves pattern matching or loading all the results and sifting through them.

Info file

Info files are now YAML format, and this is covered in detail elsewhere, but here's what I came up with:

dicefield.info.yml

name: Dice field
type: module
description: A way of specifying a dice value such as 1d6 or 2d8+3.
package: Field types
version: 1.0
core: 8.x
 
dependencies:
  - field

This is nice and straightforward, and, obviously, our module must depend on the core field module, or it cannot work at all.

Note that Drupal 8 no longer requires anything more than an info file to enable a module; previous versions required an empty .module file at least.

Field base

Now things get interesting. We're going to create a new plugin class to define our field type. The system generally works by extending one of the existing types and making the necessary changes to it. This is the biggest piece of advice I can give beyond reading articles like these: do as little work as possible! Copy/paste from existing things in core or contributed modules and change them to suit (although obviously give credit where it's due).

It's worth noting that, unlike in Drupal 7, our dicefield.info.yml file does not contain a list of "includes" that Drupal 8 should know about. These are loaded automatically by the PSR-4 autoloader, which is both more efficient and more convenient than the previous method. It does mean, however, that you must be careful to lay out your folder structure carefully and make sure things are named properly, because these things do matter in Drupal 8.

src/Plugin/Field/FieldType/Dice.php

/**
 * @file
 * Contains \Drupal\dicefield\Plugin\Field\FieldType\Dice.
 */
 
namespace Drupal\dicefield\Plugin\Field\FieldType;
 
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
 
/**
 * Plugin implementation of the 'dice' field type.
 *
 * @FieldType (
 *   id = "dice",
 *   label = @Translation("Dice"),
 *   description = @Translation("Stores a dice roll such as 1d6 or 2d8+3."),
 *   default_widget = "dice",
 *   default_formatter = "dice"
 * )
 */
class Dice extends FieldItemBase {
  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return array(
      'columns' => array(
        'number' => array(
          'type' => 'int',
          'unsigned' => TRUE,
          'not null' => FALSE,
        ),
        'sides' => array(
          'type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
        ),
        'modifier' => array(
          'type' => 'int',
          'not null' => TRUE,
          'default' => 0,
        ),
      ),
    );
  }
 
  /**
   * {@inheritdoc}
  */
  public function isEmpty() {
    $value1 = $this->get('number')->getValue();
    $value2 = $this->get('sides')->getValue();
    $value3 = $this->get('modifier')->getValue();
    return empty($value1) && empty($value2) && empty($value3);
  }
 
  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    // Add our properties.
    $properties['number'] = DataDefinition::create('integer')
      ->setLabel(t('Number'))
      ->setDescription(t('The number of dice'));
 
    $properties['sides'] = DataDefinition::create('integer')
      ->setLabel(t('Sides'))
      ->setDescription(t('The number of sides on each die'));
 
    $properties['modifier'] = DataDefinition::create('integer')
      ->setLabel(t('Modifier'))
      ->setDescription(t('The modifier to be applied after the roll'));
 
    $properties['average'] = DataDefinition::create('float')
      ->setLabel(t('Average'))
      ->setDescription(t('The average roll produced by this dice setup'))
      ->setComputed(TRUE)
      ->setClass('\Drupal\dicefield\AverageRoll');
 
    return $properties;
  }
}

This looks quite complicated and also quite alien from most things in Drupal 7 unless you're used to working with ctools plugins or the migrate system. Let's break it down a little bit.

The namespace

We have defined our namespace at very nearly the top of the file:

namespace Drupal\dicefield\Plugin\Field\FieldType;

The standard way is to use the Drupal namespace, followed by the name of your module (exactly the same as the name of the folder your module lives in), then the other bits. It's this namespace that will tell the PSR-4 autoloader where to find the classes it needs, so make sure it's correct!

Annotation-based plugin definition

There are multiple ways of defining the plugin's core data. The standard Drupal 8 way is to use annotations, which are like code comment blocks, but contain actual code rather than a comment. Other ways include YAML files, for example, but we're going to keep things simple here.

Note that one downside to using annotations to define plugin data is that since they are effectively comments, not all IDEs can interpret them in the same way as code, so you lose the syntax highlighting and code suggestions associated with writing PHP code in a modern IDE (we use PhpStorm internally). While this might look bad, it's actually not a huge deal because:

  • The plugin definition is a tiny part of your overall code base.
  • The code is right there in front of you, instead of in a separate file.
  • There are still other options if you really don't like it.

Here's the code in question:

/**
 * Plugin implementation of the 'dice' field type.
 *
 * @FieldType (
 *   id = "dice",
 *   label = @Translation("Dice"),
 *   description = @Translation("Stores a dice roll such as 1d6 or 2d8+3."),
 *   default_widget = "dice",
 *   default_formatter = "dice"
 * )
 */

Everything starting from the @FieldType is the plugin definition and everything above is just a regular comment, so you can still write a useful description if you like (and in fact, you should).

The @FieldType part tells Drupal 8 that it is a new field type. There are other annotations that can define various things in Drupal, and we'll see a few others later in the article.

There are a number of key/value pairs in the definition, and these work as follows:

  • id is used to give this plugin a machine name. This only needs to be unique for the type of thing being defined here, so you could have a FieldType called "dice" and also a FieldFormatter called "dice" without worrying about the implications of a namespace collision.
  • label uses the @Translation() notation, which is just like using Drupal's t() function, and provides a human-readable name to be used in the admin UI and other places.
  • description also uses @Translation and just lets users know what your field is for.
  • default_widget is the machine name of the widget that will be used, by default, when this field is put in place on an entity. If there are multiple widgets available, users will be able to pick, but this will be the default. Note that this refers to the machine name of the widget, not the class name. Drupal makes this distinction a lot, so you will become used to working with two different types of notation: Drupal internal machine names, and class names. The class name is not needed here. As long as we define a @FieldWidget plugin later, with an id of "dice", we will be good to go.
  • default_formatter works the same way as default_widget, but is used for the formatter (what the user sees on the front end, rather than the way data are put into your field). Note how these both have the same name. Because they're different plugin types (one is a FieldWidget and the other is a FieldFormatter), they can have the same name and Drupal 8 won't get confused.

There are also a number of other keys that you can use here, but these are best detailed by the Drupal documentation on Entity annotation, and we've covered the ones we need.

Extending classes

Nearly every class you write in Drupal 8 will extend another class, or implement an interface, or apply a trait, or perhaps any combination of those. For example:

class Dice extends FieldItemBase {

We are extending from the base field class here and this will give us all of the functionality we need to implement a new field type. All we have to do is override the methods that we want to work in a different way.

The schema

The schema is simply the definition for how the data will be stored (in the database, or whatever storage engine you're using). We need to return an array (apparently we're still stuck in "array inception" mode for some parts of Drupal 8 but thankfully this is now a lot less common) of arrays, that contain arrays that define the columns we want to store. Yeah, that.

/**
 * {@inheritdoc}
 */
 public static function schema(FieldStorageDefinitionInterface $field_definition) {
   return array(
     'columns' => array(
       'number' => array(
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => FALSE,
       ),
       'sides' => array(
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
       ),
       'modifier' => array(
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
  );
}

We are basically only defining the columns key in the outer array. In practice it's probably a good idea to define indexes and possibly also foreign keys if your fields will be linked to other data, but let's keep things simple for now.

The definitions in columns work the same way as the Drupal 8 schema API which you can use for reference if you need to.

Notice we're defining three integer fields: one for the number of dice, one for the number of sides on each die, and one for the modifier.

The number of dice and the sides are mandatory, so they do not have a default value. However, you can safely assume that unless otherwise stated, the modifier is optional, and should default to zero, which is why this one has a default value.

Note also that the first two are unsigned, because you can't have a die with -6 sides. The modifier is not unsigned, because both +3 and -3 are valid for modifiers.

The final thing worth mentioning here is that we're only defining fields that are actually stored as data. Later on, we'll see how to derive a computed field, but since the field is a calculated value (which is then cached in the render cache, so stop sweating about performance already!) it is not stored in the database and shouldn't be defined here.

isEmpty

It's very important to tell Drupal how to know if your field is empty or not. Without this, certain basic field functionality will not work properly. In our case, it's quite straightforward: the field is only really "empty" if none of the three values contain anything.

/**
 * {@inheritdoc}
 */
public function isEmpty() {
  $value1 = $this->get('number')->getValue();
  $value2 = $this->get('sides')->getValue();
  $value3 = $this->get('modifier')->getValue();
  return empty($value1) && empty($value2) && empty($value3);
}

Notice how we're using the internal method $this->get() to grab the value? The properties attached to the field will be called the same thing as those in propertyDefinitions() (see below). It makes sense for them to also match the properties we have defined in schema() above, but this does not necessarily have to be the case. Just have a good reason for doing otherwise!

propertyDefinitions

Next, we define the properties that this field will have. These will be the individual pieces of data we can retrieve from the field, and will affect things like view sorting order and how we will set up our formatter later.

/**
 * {@inheritdoc}
 */
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
  // Add our properties.
  $properties['number'] = DataDefinition::create('integer')
    ->setLabel(t('Number'))
    ->setDescription(t('The number of dice'));
 
  $properties['sides'] = DataDefinition::create('integer')
    ->setLabel(t('Sides'))
    ->setDescription(t('The number of sides on each die'));
 
  $properties['modifier'] = DataDefinition::create('integer')
    ->setLabel(t('Modifier'))
    ->setDescription(t('The modifier to be applied after the roll'));
 
  $properties['average'] = DataDefinition::create('float')
    ->setLabel(t('Average'))
    ->setDescription(t('The average roll produced by this dice setup'))
    ->setComputed(TRUE)
    ->setClass('\Drupal\dicefield\AverageRoll');
 
  return $properties;
}

Note that we have the same three properties that we defined as being stored in schema() above, plus a fourth one, called average. This is a computed field, which means that instead of storing the value in the database, we derive it from the values of the other fields. It is more useful to do it this way, because the average value is just the sum of the minimum and maximum possible roll, halved, then added to the modifier. If we were to store this in the database we would be wasting database space. You might think it inefficient to compute this value, but in fact, it's cached by Drupal's render cache system, and invalidated only when the field is updated, so except for the first time it's computed, it's not generally a performance hindrance.

Each of our four properties are basic types as defined by Drupal's typed data API. We have three integers and a float, but we could also use string or other types if we wanted to. We could even come up with our own types, but that's not necessary for this field so I won't cover it here.

We just return an array of properties by using DataDefiniton::create() and chaining the methods we want in order to create the property. As a minimum, you should use setLabel() and setDescription, but there are plenty of others that you can use. The fourth property, average, has two extra methods.

setComputed() is used to indicate that this field is computed rather than stored in the database, so there won't be a matching column in schema().

Given that it's computed, Drupal needs to know what class to use to do this computation, and this is where setClass() comes in. See below for more about computing field values in their own classes.

Widget

Now that we've set up our field base, we need to set up a widget so that people editing a node (or other entity) where this field is used are able to input or edit the data.

src/Plugin/Field/FieldWidget/DiceWidget.php

/**
 * @file
 * Contains \Drupal\dicefield\Plugin\Field\FieldWidget\DiceWidget.
 */
 
namespace Drupal\dicefield\Plugin\Field\FieldWidget;
 
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
 
/**
 * Plugin implementation of the 'dice' widget.
 *
 * @FieldWidget (
 *   id = "dice",
 *   label = @Translation("Dice widget"),
 *   field_types = {
 *     "dice"
 *   }
 * )
 */
class DiceWidget extends WidgetBase {
  /**
   * {@inheritdoc}
   */
  public function formElement(
    FieldItemListInterface $items,
    $delta,
    array $element,
    array &$form,
    array &$form_state
  ) {
    $element['number'] = array(
      '#type' => 'number',
      '#title' => t('# of dice'),
      '#default_value' => isset($items[$delta]->number) ? $items[$delta]->number : 1,
      '#size' => 3,
    );
    $element['sides'] = array(
      '#type' => 'number',
      '#title' => t('Sides'),
      '#field_prefix' => 'd',
      '#default_value' => isset($items[$delta]->sides) ? $items[$delta]->sides : 6,
      '#size' => 3,
    );
    $element['modifier'] = array(
      '#type' => 'number',
      '#title' => t('Modifier'),
      '#default_value' => isset($items[$delta]->modifier) ? $items[$delta]->modifier : 0,
      '#size' => 3,
    );
 
    // If cardinality is 1, ensure a label is output for the field by wrapping
    // it in a details element.
    if ($this->fieldDefinition->getFieldStorageDefinition()->getCardinality() == 1) {
      $element += array(
        '#type' => 'fieldset',
        '#attributes' => array('class' => array('container-inline')),
      );
    }
 
    return $element;
  }
}

Class

Once again, we are inheriting from the base WidgetBase class because almost all of the work involved in being a widget is done for us, so we only need to lift a finger to tell Drupal what's different from the base.

class DiceWidget extends WidgetBase {

Annotation

Again, we see that the annotation at the top of the class defines basic data on this widget:

/**
 * Plugin implementation of the 'dice' widget.
 *
 * @FieldWidget (
 *   id = "dice",
 *   label = @Translation("Dice widget"),
 *   field_types = {
 *     "dice"
 *   }
 * )
 */

This time, @FieldWidget tells Drupal it's dealing with a widget, and the id and label properties work the same way as for the base field above.

We have an array this time, in the form of field_types, which tells Drupal which types of field are allowed to use this widget. Note that unlike regular PHP arrays in Drupal, you must not put a comma after the last element in these arrays.

This field_types allows us to create new widgets, even for existing field types, in case we want a better or different way of inputting data. For example, a geo-location field that stores map coordinates might have a text widget for inputting the data manually, and a separate map widget that allows the user to click on a map to choose a point.

formElement

In actual fact, we only need to override one method in this class:

  /**
   * {@inheritdoc}
   */
  public function formElement(
    FieldItemListInterface $items,
    $delta,
    array $element,
    array &$form,
    FormStateInterface $form_state,
  ) {
    $element['number'] = array(
      '#type' => 'number',
      '#title' => t('# of dice'),
      '#default_value' => isset($items[$delta]->number) ? $items[$delta]->number : 1,
      '#size' => 3,
    );
    $element['sides'] = array(
      '#type' => 'number',
      '#title' => t('Sides'),
      '#field_prefix' => 'd',
      '#default_value' => isset($items[$delta]->sides) ? $items[$delta]->sides : 6,
      '#size' => 3,
    );
    $element['modifier'] = array(
      '#type' => 'number',
      '#title' => t('Modifier'),
      '#default_value' => isset($items[$delta]->modifier) ? $items[$delta]->modifier : 0,
      '#size' => 3,
    );
 
    // If cardinality is 1, ensure a label is output for the field by wrapping
    // it in a details element.
    if ($this->fieldDefinition->getFieldStorageDefinition()->getCardinality() == 1) {
      $element += array(
        '#type' => 'fieldset',
        '#attributes' => array('class' => array('container-inline')),
      );
    }
 
    return $element;
  }

This method tells Drupal how to render the form for this field. Because we need to know three things (the number of dice, the sides per die, and the modifier), we will provide three fields for this. Note how the form keys for these fields match what we defined in schema() and propertyDefinitions() above.

The #attributes on the fieldset causes the fields to be displayed inline instead of one line after another.

These fields use the number field type, which is basically a text field but with little up and down arrows that can be used to increase or decrease the value. It also provides some basic validation in that you need to put a numerical value in here, not a string, and there's no need to write this validation if it's already done for us.

The #default_value key shows how to extract the value from the current field. In the case where we're editing a field, we want the existing values to be in the form ready to be changed, and $items[$delta]->PROPERTY_NAME will do that for us.

I have also set up a default value in the case where we're creating a completely new node, as I felt it was nice to be able to show an example of the required input. Also, since the modifier is often zero, it makes sense to set this as a default value. I could have also used #placeholder to put an HTML5 placeholder value in the field instead of real input.

The last part of this method simply adds a fieldset so that if the field cardinality is 1 (only 1 "dice roll" field value can be put in, instead of allowing unlimited, or a higher number of entries), then the label for the field will still show up properly. This can be used as-is for most field widgets.

Formatter

The last required step (and it might not even be required if you can re-purpose a core formatter from Drupal itself) is to set up a new formatter. This will output the information in the field onto the screen so that users can see it.

src/Plugin/Field/FieldFormatter/DiceFormatter.php

/**
 * @file
 * Contains \Drupal\dicefield\Plugin\Field\FieldFormatter\DiceFormatter.
 */
 
namespace Drupal\dicefield\Plugin\Field\FieldFormatter;
 
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
 
/**
 * Plugin implementation of the 'dice' formatter.
 *
 * @FieldFormatter (
 *   id = "dice",
 *   label = @Translation("Dice"),
 *   field_types = {
 *     "dice"
 *   }
 * )
 */
class DiceFormatter extends FormatterBase {
  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode = NULL) {
    $elements = array();
 
    foreach ($items as $delta => $item) {
      if ($item->sides == 1) {
        // If we are using a 1-sided die (occasionally sees use), just write "1"
        // instead of "1d1" which looks silly.
        $markup = $item->number * $item->sides;
      }
      else {
        $markup = $item->number . 'd' . $item->sides;
      }
 
      // Add the modifier if necessary.
      if (!empty($item->modifier)) {
        $sign = $item->modifier > 0 ? '+' : '-';
        $markup .= $sign . $item->modifier;
      }
 
      $elements[$delta] = array(
        '#type' => 'markup',
        '#markup' => $markup,
      );
    }
 
    return $elements;
  }
}

Annotation

The annotation defines the basic formatter data, and works just like the others above.

  /**
   * Plugin implementation of the 'dice' formatter.
   *
   * @FieldFormatter (
   *   id = "dice",
   *   label = @Translation("Dice"),
   *   field_types = {
   *     "dice"
   *   }
   * )
   */

In fact, this is almost identical to the one for DiceWidget that we defined above, except we're now using the @FieldFormatter type.

Class

As we've seen above, it's easiest to just extend the base class, FormatterBase, since this does all the heavy lifting already and we can pick and choose what to override.

class DiceFormatter extends FormatterBase {

viewElements

We are overriding the method that actually produces the markup that will be displayed on the page:

/**
 * {@inheritdoc}
 */
public function viewElements(FieldItemListInterface $items, $langcode = NULL) {
  $elements = array();
 
  foreach ($items as $delta => $item) {
    if ($item->sides == 1) {
      // If we are using a 1-sided die (occasionally sees use), just write "1"
      // instead of "1d1" which looks silly.
      $markup = $item->number * $item->sides;
    }
    else {
      $markup = $item->number . 'd' . $item->sides;
    }
 
    // Add the modifier if necessary.
    if (!empty($item->modifier)) {
      $sign = $item->modifier > 0 ? '+' : '-';
      $markup .= $sign . $item->modifier;
    }
 
    $elements[$delta] = array(
      '#type' => 'markup',
      '#markup' => $markup,
    );
  }
 
  return $elements;
}

The most important thing here is that we loop through the $items because each field could have a cardinality of greater than one, meaning multiple dice rolls can be stored in a single field.

There is a fringe case where technically it's possible (not in the physical world) to have a one-sided die, which will always roll a 1, no matter what, so instead of writing 1d1, we tell the formatter to present it as just 1 for clarity.

Next we add the modifier, but only if it's a non-zero, because 1d6 looks cleaner than 1d6+0. Note that the modifier could be positive or negative, so we need to account for that in the code. Negative numbers, when converted to strings, already have a negative symbol at the front, but positive ones don't, so we add that on.

The last part is quite important, and that is presenting the return value as a series of render arrays, rather than just plain text. Everything should be presented as a render array where possible, because this allows Drupal to delay its rendering until the last possible moment, affording other modules the opportunity to override where necessary.

AverageRoll type

Earlier, we defined a computed field when we set up propertyDefinitions(). This means that we need to tell Drupal how to compute the value of this field, and we will create a separate class for this.

src/AverageRoll.php

/**
 * @file
 * Contains \Drupal\dicefield\AverageRoll.
 */
 
namespace Drupal\dicefield;
 
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\String;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\Core\TypedData\TypedData;
 
/**
 * A computed property for an average dice roll.
 */
class AverageRoll extends TypedData {
 
  /**
   * Cached processed value.
   *
   * @var string|null
   */
  protected $processed = NULL;
 
  /**
   * Implements \Drupal\Core\TypedData\TypedDataInterface::getValue().
   */
  public function getValue($langcode = NULL) {
    if ($this->processed !== NULL) {
      return $this->processed;
    }
 
    $item = $this->getParent();
 
    // The minimum roll is the same as the number of dice, which will occur if
    // all dice come up as a 1. Then apply the modifier.
    $minimum = $item->number + $item->modifier;
 
    // The maximum roll is the number of sides on each die times the number of
    // dice. Then apply the modifier.
    $maximum = ($item->number * $item->sides) + $item->modifier;
 
    // Add together the minimum and maximum and divide by two. In cases where we
    // get a fraction, take the lower boundary.
    $this->processed = ($minimum + $maximum) / 2;
    return $this->processed;
  }
 
  /**
   * Implements \Drupal\Core\TypedData\TypedDataInterface::setValue().
   */
  public function setValue($value, $notify = TRUE) {
    $this->processed = $value;
 
    // Notify the parent of any changes.
    if ($notify && isset($this->parent)) {
      $this->parent->onChange($this->name);
    }
  }
}

There is no annotation!

Since we're not defining a plugin here, there's no annotation at the top of this class. There's no need.

Class

We are simply extending an existing type, to do the heavy lifting for us, as with previous classes above.

class AverageRoll extends TypedData {

Caching

I mentioned earlier that Drupal's render cache means that we only need to process the value when it changes, rather than every time we see the field, and we can add a mechanism to achieve this. It's via a protected property:

/**
 * Cached processed value.
 *
 * @var string|null
 */
protected $processed = NULL;

Note how even though this is just a property on a class, it is still fully documented like anything else!

getValue

This method will, as the name suggests, get the value of the computed field when Drupal asks for it. Note that method doesn't need to be called directly. Drupal takes care of this internally which means that you can just use $item->average instead of having to write $item->average->getValue() or anything complicated like that.

/**
 * Implements \Drupal\Core\TypedData\TypedDataInterface::getValue().
 */
public function getValue($langcode = NULL) {
  if ($this->processed !== NULL) {
    return $this->processed;
  }
 
  $item = $this->getParent();
 
  // The minimum roll is the same as the number of dice, which will occur if
  // all dice come up as a 1. Then apply the modifier.
  $minimum = $item->number + $item->modifier;
 
  // The maximum roll is the number of sides on each die times the number of
  // dice. Then apply the modifier.
  $maximum = ($item->number * $item->sides) + $item->modifier;
 
  // Add together the minimum and maximum and divide by two. In cases where we
  // get a fraction, take the lower boundary.
  $this->processed = ($minimum + $maximum) / 2;
  return $this->processed;
}

At the beginning of this method is the test to see if we have already assigned a value to $this->processed. If we have, we don't need to compute the value. We only do that part if the value is null, to save on processing power.

The internals of this method first work out the minimum and maximum possible rolls, applying the modifier to each, and then divide their total by two, which gives the average. For many dice rolls this will be a fraction, which is why we have defined this field as a float rather than an integer.

setValue

Lastly, to make sure cache invalidation works correctly, we need to define a method to take care of setting our value:

/**
 * Implements \Drupal\Core\TypedData\TypedDataInterface::setValue().
 */
public function setValue($value, $notify = TRUE) {
  $this->processed = $value;
 
  // Notify the parent of any changes.
  if ($notify && isset($this->parent)) {
    $this->parent->onChange($this->name);
  }
}

Here, we set $this->processed to the new value, but we also notify the class's parent via the onChange() method. Remember that the vast majority of implementation is handled by the base class instead of making us do the work here, so we ought to be happy to pass the buck to Drupal itself where we can!

AverageRollFormatter

Lastly, it's worth bearing in mind that we have a formatter than can display the dice roll itself, and we also have a computed field that can calculate the average roll, but we have no way of actually showing the average roll to the end user. We will create one more formatter class that will take care of this for us. Because this is a separate formatter, it will allow the site administrator to choose, when displaying dice fields (in views, say), whether to show the dice notation, the average value, or even both (by adding the field twice with different formatters).

src/Plugin/Field/FieldFormatter/AverageRollFormatter.php

/**
 * @file
 * Contains \Drupal\dicefield\Plugin\Field\FieldFormatter\AverageRollFormatter.
 */
 
namespace Drupal\dicefield\Plugin\Field\FieldFormatter;
 
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
 
/**
 * Plugin implementation of the 'average_roll' formatter.
 *
 * @FieldFormatter (
 *   id = "average_roll",
 *   label = @Translation("Average roll"),
 *   field_types = {
 *     "dice"
 *   }
 * )
 */
class AverageRollFormatter extends FormatterBase {
  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode = NULL) {
    $elements = array();
 
    foreach ($items as $delta => $item) {
      $elements[$delta] = array(
        '#type' => 'markup',
        '#markup' => $item->average,
      );
    }
 
    return $elements;
  }
}

The details here are much the same as our DiceFormatter from above, but the implementation is even more simple. Since the value of the field is computed for us already, all we need to do is print it out (by putting it into a render array) in viewElements().

One thing to bear in mind here is that we could have done the average calculation directly in the formatter. There's certainly scope for it: we have all the field data and the ability to execute whatever custom code we like. However, this would have been the wrong thing to do because it would have meant that the average can only be displayed on the front end, and not accessible internally to Drupal. By doing it the way we have done it above, we ensure that, for example, views is able to sort this field by average value, or another developer can plug into this module and grab the average value for his or her own use.

Wrapping up

Now that you have all the elements in place, you can enable the module and try it out!

Once enabled, you will see the new "dice roll" option when picking a field type to add to an entity. When added, you can try creating a new entity of this type, and see the widget in action. Then, the formatter will take care of showing the end result on your entity's view page. Don't forget: you have a choice of two formatters, so you can either show the dice notation or the average value (or even both if you use a custom template or views).

If you have any comments, corrections or observations about this tutorial, please feel free to leave them in the comments below. Hopefully the information about the principles and design decisions will be useful!

The full codebase is available on Github.

Feb 11 2016
Feb 11
teaser image for blog post

This months Northwest Drupal User Group (NWDUG) in Manchester had a lovely visit from a non developer to talk about how the Internet has changed his life and the challenges of using the Internet as a blind person.

Being blind since he was a child has meant that some activities weren't possible before the Internet became accessible to everyday people - such as reading the news or magazine articles. Now Sunil works with the Internet everyday at his job in the British Red Cross.

Many years ago JAWS was the defacto screen reader that accessible sites were tested against and made the Windows operating system more popular amongst the blind community. Since Apples VoiceOver capabilities have been baked in to their OS X software its opened up better applications to navigate the web. It was also noted that nearly all blind people tend to prefer iPads and iPhones because of their mature and built in accessibility features - and the interface controlled with flicks and swipes to the touch screen.

The group were given a demo of navigating the Guardian news website being navigated in the Safari web browser. The VoiceOver facility describing all the elements on the page read out the descriptions at a high speed to transmit the vast amount of information needed.

Sunil said he used headings to jump to content he's looking for - H1 etc. HTML tags.  Interestingly the "skip to main content" link right at the top of the page (and often found in Drupal base themes) wasn't used! A comment from the audience did suggest that those links are great for sighted users navigating sites with the keyboard.

He found the ALT attribute on images useful, if present, although TITLE attributes should contain the descriptions of what is in the image.

Forms with clearly labeled fields help associate form validation error messages with the bad input. 

The CAPTCHA anti spam systems still create a mixed problem - implementations that offer disability support are hard to hear and so difficult to solve. Sunil's favorite are the logic questions such as maths or odd word in a list. Google's more recent ReCAPTCHA now removes all these problems and replaces it with a simple tick box. A Drupal module is also available to support this service on forms.

In recent years the European cookie compliance policy pop ups have invaded many of our websites -- ones which appear at the top of the page tend to be a mild irritant but once accepted they don't re-appear - so just as relevant to all of us. Prehaps putting the cookie warning at the bottom of the site is a better solution?

In a similar vein the topic of pop-up banner advertising was asked by the group -- is it a problem or inconvenience when browsing a site? Sunil mentioned he had previously used Ad blocking software years ago but these days banners don't get in the way of his reading -- although he doesn't know what the advertising is due to it usually being image based (advertising networks take note!).

One gripe that still exists even in modern website builds is the use of PDF files for text information such as restaurant menus. if that information could be duplicated as HTML page content it would make consumption of the information possible for all.

It seemed that there's not much else that can stop Sunil from navigating the web in 2015 - which is great news as Drupal site builders!

We've had general web accessibility guidelines (WCAG) for many years but it's refreshing to see how that translates in to the real world, and a great thanks to @SunilPeck for giving up his evening to visit the Drupal usergroup.

The full evenings talks are available every month on YouTube on the NWDUG channel. You can watch Sunil in the February 2016 session.

Photo at NWDUG thanks to @ChandeepKhosa.

Feb 03 2016
Feb 03

As of 1:23pm GMT on Febuary 3rd 2016 there are no dependencies in the Drupal 8.1.x git branch.

Why?

There was no reason to have them there. It makes the repository bigger, and therefore takes longer to download. No one else does it.

What does it mean?

Not much really.

If you download Drupal via the zip file or tarball then the drupal.org packager will run composer so the dependencies will be there for you.

If you submit a Drupal core patch on drupal.org then DrupalCi testbot will run composer install.

It’s only if you clone Drupal 8.1.x or higher directly from git, you will need to run composer install in the Drupal root directory

Top tip: composer install --prefer-source --no-interaction can often be quicker.

Please enable JavaScript to view the comments powered by Disqus.

blog comments powered by
Jan 19 2016
Jan 19

DPSX-jan-2016DPSX-jan-2016 Our January meet up was in the making since the #DPSX BoF at DrupalCon Barcelona in September 2015, the sign up for the 13th Jan event was great but logistical challenges mid December left quite a few folks confused. In retrospect the meet up needs a permanent abode, if you’d like to host the next meet up please get in touch.

Despite that the turn out was good, we had 11 from a possible 29 and one late arrival found the venue doors locked! apologies Chris, have expressed much annoyance with the venue management.

We had Greater London Authority, Crawley borough council and Lambeth Council representing the public sector along with folks from the Drupal community.

The theme for the evening was ‘A Drupal Distribution for Local Councils’ though discussions as always went beyond the theme, other subjects that made for a lively discussion included Agile colocation, G-cloud for local government procurement, user lead design and next steps to making a local gov distribution happen!

Obvious place to start the conversation was GovCMS, as it turned out Andy from Lambeth had a look but did not go with it, likewise the general consensus was there is too much there for a local council and by the time you’re done stripping stuff out and adding to it you’d have forked it significantly! and of course there is the ’not invented here’ factor too. GLA tried Panopoly with one supplier only to have the next one rip it out, which turned out to be the right decision for GLA.
General reluctance towards distributions; few found them to be cumbersome and perhaps best suited for proof of concepts and demos but not the real thing. Consensus was getting to a distribution for local councils in the UK ought to start by utilising a local council’s existing platform as the base, the requirements are likely to follow the 80/20 rule – 80% common across and 20% custom, with the custom requirements most likely to be integrations with back end systems. Questions raised included which council’s platform would be the base? this would require a discovery, setting out a minimum viable product (MVP) criteria, an evaluation criteria, getting buy-in to the concept, evaluating contenders etc.. the other key aspect to consider for a local council distribution is keeping it minimal! if overloaded with features it will fall by the wayside as cumbersome.

The discussion went on to how could we make it happen? Chandeep is certain there is an initiative in the making (shall reach out to the local community to explore further) and if you happen to be involved in it please reach out to the #DPSX community here. A to do for me is to reach out to Ben Goward from Westminster, Kensington & Chelsea and Hammersmith & Fulham councils and explore their initiatives on shared digital platform and services. For the next meet up it would be invaluable to get a few more councils represented, explore if there is an initiative on a local gov/council specific distribution and to put in a process to capture the minimum viable product (MVP) criteria. Shall update everyone with a followup post as and when I have news either way.

For this post I will pick one more topic from our meet up to keep it brief, that being User lead design at local councils and making the most of the Government Digital Services’s (GDS) user testing lab and services. Agile co-location and G-cloud shall share in separate posts. 

Graham informed the group that GLA placed a great deal of emphasis on ensuring the solution followed user lead design principles and practises, and for that the GLA called on the Government Digital Services’s (GDS) user testing lab and services, GLA accessed the GDS testing lab and had the benefit of working with the GDS’s design team. This is a huge takeaway for all local Gov representatives reading this post, for local council product owners it would be hugely beneficial to enquire that sort of access and service costs, or reach out to the GLA to share the learnings. I’d like to point out to an earlier post on better understanding your jury (your users), and if you’d like to learn more about persona driven user journeys then you’d benefit from the following resources:

This is relevant to our conversation on distributions too, for most if not all distributions appear to me as engineering lead, whereas they ought to be user-need / problem-solution driven. If approached from the problem-solution view I have no doubt we would have leaner, more focused distributions that address vertically focused user needs which in turn would mean increased uptake, lower cost of ownership and quicker release cycles. A valuable exercise to under take would be to develop a empathy map for local councils to identify their digital behaviour as an organisation, I sense a #DPSX workshop evening in the making!

The resolution for 2016 is to hold more frequent DPSX meet ups and with that in mind I’ve set up a meetup.com group which ought to make it easier to coordinate and grow the community, you can sign up and keep track of our meet ups here. The next meet up is planned to coincide with Drupal Camp London, we’ll be holding a BoF at Drupal Camp London (4-6th March 2016) (details to be confirmed).

Lastly I’d like to thank our sponsors Acquia and FFW for their support with the venue and refreshments for the evening.

Dec 01 2015
Dec 01

This week a lot got undone, broken, recovered and then some.

Worked on the product backlog, not quite ready for public consumption yet but getting there, sprint backlog for the week:

  • Shop for VPS
  • Setup VPS 
  • Migrate to VPS
  • Fonts – via CSS
  • Sort out Contact Form (emails not working)
  • Sort our Domain name and DNS stuff (may need an expert’s assistance)
  • Backlog grooming – WIP

Acquia Cloud Professional would be nice, would make life much easier, support would be kick ass (and needed) but is out of my budget! time to count the pennies and find a candy store that fits the budget. Bluehost.com or DigitalOcean.com…. went with DigitalOcean, gives an SSD, quite a bit of computing power on a budget, has no developer tools though, will need to get devops help and learn some devops stuff myself (kind’a and kind’a not looking forward to that) but hey you get what you can afford!

  • Added an SSH key, instructions easy enough to follow
  • Am in as root! (nice!)
  • its an Ubuntu VPS, LAMP stack, phpmyadmin installed
  • explored setting up DNS and nada – haven’t got time for this, my sprint capacity is significantly reduced this week and possibly the next too! can’t wait, time to call in devops help, Asim enlisted to help set up DNS for agileforpeace.com for the VPS and opensocial.agileforpeace.com for my social transformation site (thank you Asif)
  • With not much to do, dived into CSS architecture (for Drupal 8)… 10 mins later… need to find an idiot’s guide to CSS in Drupal!
  • Had good wins today, the fear of the terminal is dissipating.
  • Need to migrate my site from Acquia Cloud to the new VPS environment.
  • Installed backup and migrate, activated it and disaster strikes! backup and migrate broke the site and can not access the extend page to uninstall.

Drupal8-brokenbymigrateDrupal8-brokenbymigrate

  • Looked up uninstall backup_migrate using Drush since I could not access the extend page – nada!
  • But if I go to an invalid URL it seems to work but can’t access anything in the admin menu, insanity!

Drupal8-brokenbymigrate01Drupal8-brokenbymigrate01

  • Tried disabling using Drush (drush dis -y backup_migrate && drush pm-uninstall -y backup_migrate), did not work, tried a bunch of stuff, whatsoever google threw up as candidate solutions.
  • Decided to take the simplest option and restored the site from backup on Acquia insight, easy enough.
  • I’ll take the small win and call it a day!
  • Started day 4 with a nice surprise, my first contribution! wooHoo.. the joy of little things!
  • It was a tough start, forgot my admin password again (blistering barnacles)! and remained locked out for the a good part of the timebox! tried a number of suggested means to recover the admin password using Drush, it was one fail after another! eventually reached out to @Dakku for help and it turns out its a pretty simple process!
  • Attempted migration from the DB back up – something migrated but not quite, need to figure out what went wrong, the theme didnt quite work even though its Bartik straight out of the box, am beginning to have doubts about maintaining a VPS by myself.

Open Social Broken 001Open Social Broken 001

  • Am back in but am out of time, more on day 5.
  • bulbbulb In terminal type: cd /var/www/html/yoursite.dev/docroot/sites/default
  • Once in the directory, type: /usr/local/bin/drush8 uli
  • You will get a return value that looks like: /user/reset/1/1448057351/JY2957SilWctPfNfN1gUQ2bT5lS-NvCwjt3heDqdu5A.
  • Copy everything from “/user/….” onwards and paste it after your domain in the address bar in the browser e.g. http://yourdomain.com/user/reset/1/1448057351/JY2957SilWctPfNfN1gUQ2bT5l...
  • Go to that url, this is a one off password change process, you can reset your admin password.

Decision time! I can spend time building my site in D8 with dev tools to support me (on Acquia Cloud) or I can build without them and pick up needed devops skills to manage my VPS; time being the deciding factor am ditching the VPS route and will continue with Acquia Cloud, as for affordability found out as an Acquian I get an environment as an employee benefit! wooHoo! Though it seems this week was not as productive but got a couple of nice wins and picked up some more Drush (the fear of the terminal is dissipating! BTW DrushCommands.com is a pretty epic resource).
Retro time

      • Shop for VPS
      • Setup VPS –
      • Migrate to VPS (theme isn’t working)
      • Fonts – via CSS
      • Sort out Contact Form (so that it sends out emails)
      • Sort our Domain name and DNS stuff (may need a subject matter expert to assist)
      • Backlog grooming – WIP

Having decided to stay on Acquia Cloud I can focus on the site backlog in week 5, (mental note: need to pick up the MVP backlog items soonish).

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Nov 28 2015
Nov 28

logo_small_sx_1logo_small_sx_1 The keynote at DrupalCamp Bulgaria was planned to be left field from the get go, however it went a little further out after Paris came under attack on the night of the 13th of November 2015.

#JeSuiBaghdad #JeSuiParis #JeSuiBeirut #JeSuiChibok #JeSuiKarachi #JeSuiMadrid #JeSuiDamascus #JeSuiAnkara #JeSuiLondon Dalai Lama Quote 2015Dalai Lama Quote 2015 #JeSuiMali the list goes on, but other than on the bench solidarity what are we doing as individuals, as a community to facilitate and help build a better safer, cohesive and a pluralist society?

As a FOSS community we are constantly talking of give-back but are we engaged enough?

How could we take the strengths and learnings that make us a successful tech community to wider non tech audiences with a view of creating social transformation that addresses the needs of our societies in these turbulent times. What can we learn from the transformation FOSS and the Cloud has had on our ecosystem as technologists and how can we export that beyond tech to heal and build a stronger society?

I have more questions for discussions than answers however there is an inflight and successful start made by Peace Through Prosperity using Agile, Open source and Cloud to deliver social transformation programs that could be a starting point for the Drupal community to engage with in their own geographies. The open source component of this program is in development and work in progress can be seen here, if you’d like to contribute and #GiveBack beyond our bubble please get in touch over Twitter or Linkedin.

Links shared within the keynote slides:

The presentation from the keynote:

Open Source and Cloud Beyond tech from Kubair Shirazee

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Nov 23 2015
Nov 23

Drupal Public SectorDrupal Public Sector

As a tax payer I want companies who provide frontline public services to make the data they gather in the provision of such services available through Open APIs to other actors in the ecosystem, so that such actors can utilise that data to provide new and innovative services to the public.

News from Australia shared with the DPSX BoF at DrupalCon Barcelona back in September was both good and bad, whilst the Australian government is spearheading adoption with the GovCMS distribution, efforts are we were told loosing steam as the distribution in its current form is quite restrictive requiring significant customisation by individual departments adopting it. The question is why fork it? why not modularise it? To get some answers that may help us in the UK I reached out to my Acquia colleagues in Australia to shed some light on the matter and this is what they had to say:

govCMS is growing and maturing at a good rate after a slow start. The fundamentals have been adjusted to allow for greater openness and govCMS_logo (3)_1govCMS_logo (3)_1 community interaction with the distro via github. The Australian Government is delivering on their aim to work with the community. We are expecting to see further iterations of the govCMS product over the next 12 months that will improve the ‘out of the box’ experience and allow clients to get sites up and running quickly/cheaply. Expect to see improvements that either reduce the need for customisation and make custom work easier.

The restrictions you mention are by design – they largely relate to the modules available to developers. By providing best of breed modules, the distro can avoid bloat/cost. The other effect is to focus expertise on those modules so they become easier to implement via experience and documentation that are relevant to this client space. That said, the process of requesting changes has also moved to github in the last few months and is less a ‘black box’ than it was initially.

As to why govCMS was forked – this largely related to the need Australian Government had to work with a stable platform where they could apply their own governance controls. This will probably mean a distro that evolves at a slow and steady pace, with a focus on security and compatibility. Australian Government is also sensitive to appearance that they are endorsing one vendor over another, or becoming subject to vendor lock in, taking ownership of the distro removes this issue and makes further broad investment by a range of departments more likely.” Gavin Tapp | Program Director | Acquia

There are valuable lessons for local councils in the UK seeking to create a local government distribution, which ought to make for engaging conversations at the 13th January 2016 meetup of the DPSX in London. If you’d like to a part of the conversations please register for the free event here:

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Nov 20 2015
Nov 20

More a log than a guide, but you get the idea! its a lengthy log this week, a lot got undone, done and then some. Backlog for the week:
  • Fonts
  • Contact Form (customise it)
  • Translations (Lingotek)  
  • Take the site online 
  • Toy around with Drush
Not part of the backlog, decided to update core, followed the instructions to the letter, used Drush and broke the site completely! ha! ‘A little learning is a dangerous thing; drink deep, or taste not the Pierian spring’ … and yes did not back it up did see Drush had created a back up but have failed to locate it! was going to take it online anyhow, so decided to rebuild on Acquia CloudSite folder on DT02Site folder on DT02 Would be interesting to see how long it takes to rebuild it! good organisation should make the task a tad bit easier! Revisions made to node/1 were not in the .txt file, extracted them from node_revision_body from the database (a little learning can be a useful thing too) – a small win on a rough day!
  • Logged into Acquia Cloud, spun up a free subscription, installed D8.rc3, and got cracking! 
  • Only downer is can’t add contrib modules without figuring out how to SFTP, or using Drush. For now staying clear of Drush! fear of the terminal is back!
  • Set up path aliases, was a quick and easy introduction and gets rid of the node/n in the address bar, of course good for SEO and all that jazz.
  • I know there is an easier way to justify text alignment via CSS but that’s going to take some time to get to grips with so taking the long but short cut with HTML to <p style=”text-align:justify”>.
  • It was a good day, a forced refresher on getting sh*t done and it took less than 2 hours to get the site back on track a little ahead of the previous version too! wooHoo! 
  • Tested the contact form but it won’t work, a bit of digging around and seems SMTP Authentication Support needs to be installed, am after a quick win today, decided to install and toy with Lingotek instead.
  • Dang it! can not upload to Acquia Dev Cloud, dug around, need SFTP or SSH access, ok set up my SSH Public Key, downloaded FileZilla, followed the instructions and nada! time to put the fear of thescreen-grab-lingotekscreen-grab-lingotek terminal behind me (again) bounced around from page to page but finally got in WooHoo! installed LingoTek in the wrong place Blistering Barnacles!
  • Tried to uninstall LingoTek, could not (commands I’m seeing online don’t work for me), Ok so the next best thing is to install LingoTek in the Dev folder but nothing in the sites folder! Bizarre! or may be not!
  • Anyway reading up on Drush and installing modules on Acquia Cloud and WTF! there is aenable live devenable live dev simpler way to do so! Why is this nugget buried so deep! Evidently all I needs to do is go to my Sites/Cloud and ‘Enable Live Development‘ 
  • That done time to check out LingoTek, copy link address, install, enable, wait, enable dependencies, enable job done! Lingotek Translation itself, lemon squeezy!

LIngo Tek grab 04LIngo Tek grab 04

  • Ending day 2 on a colossal WIN, I have translations for basic pages and articles in Arabic, Bulgarian, French, Hindi, Spanish and Urdu, the main and footer menus are not translated as yet, neither do I have language select buttons/icons enabled, to access the languages I have to go by the language code in the URL and its not perfect I still need our Peace Through Prosperity volunteers to check and edit  multilingual content but they’ll  have less to do. LingoTek kicks ass!
  • Time to take on the font challenge!
  • Noticed whilst on my local environment I was having problems installing modules, kept getting error messages that told me nothing other than it’s an error (FFS!), however haven’t been getting many of those on the Cloud.
  • AnyHoo, for fonts decided on Google Webfont Loader API, comes highly recommended by @Dakku and has a D8 recommended release out too, so what could go wrong. Installed, enabling took ages and it works but… there are only two font added to the library of fonts  (not exactly a library!), all a bit anti-climatic!
  • Not quite what I expected, font attempt five or is it six now is a fail! uninstalled the Google Webfoot Loader API and am going to start exploring the CSS route one of these days. 
  • Its Menu translation day – why hasn’t LingoTek got an automated workflow for menu item translations? got it done but what a pain! suggested improvement for LingoTek: have multiple language translations for a menu item on the same page please! a lot of unnecessary back and forth in the workflow.
  • Decided to spend time on CSS so that I need not rely on modules to change fonts and to get the menu translations in place between day 4 and 5, SMTP set up and the contact form will have to wait its seems a bit complicated and will need help on this in the know, as a starter have bookmarked CSS architecture (for Drupal 8) and Drupal 8 Theming Fundamentals to my reading list.
Its a big day, the WIP site gets opened up for demo on the blog!  Retro time!
  • Fonts – tackled again, failed, avoided (need dragon glass to tackle this one)
  • Contact Form (customise it)
  • Translations (Lingotek)
  • Take the site online
  • Toy around with Drush
  • Backlog grooming
..and disaster strikes! somehow managed to lock myself out! can’t recall the password! dang it! it was such an awesome run! need help on this, tried SSH, can SSH but getting access denied for getting DB backups and hesitant to do too much using Drush, remember day 1’s lesson well. Added @Dakku to the Site ’Team’ on Acquia Cloud and its all good.  Week three has been an epic adventure! am clearly trying to run before I can walk but am finding the platform is coaxing me to do so! what little surface I have scratched has opened up a whole bunch of stuff to add to the open social backlog and am getting pretty confident quite a bit of it could be handled by myself! yes humility is a must have EM trait!. Week four will start with an upgrade to Drupal 8.0.0 WooHoo…! in the mean time feast on this…..in seven languages! Open Social Transformation PTP03Open Social Transformation PTP03

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Nov 12 2015
Nov 12

More a log than a guide, but you get the idea! Day 1’s timebox went on user stories and sprint goals (1 week sprints btw); this sprint’s goals are;
  • main menu,
  • footer menu,
  • social (Twitter) feed
  • static content for pages
  • font face
  • Favicon
The allocated time b/w days 2 and 5 are 3 hours in total, so lets see how I fare this week. Started with aesthetics in the hope they’d be the easy wins. 
  • Changing font face – fail: Googled and it appears all I need to do is change the font type in a style.css filesite building D8 font issuesite building D8 font issue , first fail was there is no style.css in the Bartik components folder, did find font types in the elements.css file, edited it, added Arial and nada!
    Went on a module hunt, found font-your-face – installed, did not work, looked up the documentation and does not show up under admin/config/settings/user interface. packing in on the should’ve been an easy win and moving to the next item on my backlog.
  • Favicon success – downloaded Favicon, installed and it has a configure link under extends, first module I’ve come across that links its settings/config page from the module description link from the Extends page (good UX, thank you dave-reid). Initially the .ico file upload didn’t work, thought it might be a cache issue, cleared cache (mysite/admin/config/development/performance) did not work, decided to try renaming the file name and wooHoo! it works. Decided to call it a day with a small win.
Bartik Block RegionsBartik Block Regions

Newbie tip bulbbulb

I took a screen grab of ‘Bartik’s block regions demonstration’, printed it and pinned it to the wall and added it to desktop 2 as a wallpaper – am sure over time I’ll know whats where but for the time being its proving to be a good idea.

WooHoo, its a Saturday and though still working on a project (not really a weekend) am going to take some out for this.
  • Twitter feeds turned out lemon squeesy, with a work around, Twitter widget in a block instead of waiting for maintainers to sort their D8 modules out, thanks Dakku. Five mins into it and job’s done, there is a now a Twitter feed widget on the site! WooHoo! got carried away added a Twitter search box on #peacebuilding and #entrepreneurship, two big wins in less than 10 mins, am on a roll!
  • Next up was Social sharing, searched selected Easy Social, downloaded, installed, read the documentation, fail…. another 10 minutes invested into it… fail fail! should have quit on a win but anyhow failed fast enough to have some time to spare on other backlog items. 
  • So over to Footer menu it is. Added a bunch of menu links but not quite what I had in mind: 
Footer 001Footer 001 Got undone on finding any attributes to the menu setup that allows for external links to be opened in a new window, dug around and found its not possible without a module to manage menu attributes, It took a little bit of time, found one that is D8 ready, and guess what… does not work! fail! Went through the Readme file nothing under admin/configurations tried getting to the  setting using /admin/config/user-interface/extlink and nada! blistering barnacles! Back on the footer menu fumbled around and wooHoo that’s more like it, now to split them out: Footer 0020Footer 0020 Am wondering if I am going about searching for modules the wrong way round for it seems like an awful waste of time trawling through different contrib modules trying to see if they are D-8 ready or not, thought there is this site that lists the status of the top 100 contrib modules it doesn’t cover all of them and when using Google the ones that do turn up are those on D.O and there is just so much noise there! All the contrib modules I have installed and all of the ones that tell me in their Readme file that I will find config links under Admin/configurations –  none have turned up on that page, and when I have tried getting to the  setting using /admin/config/modulename/settings have had no joy either! this pattern suggests something is going wrong with my install! maybe!?” cleared cache too and still nada! more blistering barnacles!! I had a partial win with Footer Menu blocks, am going to take that and come back to this another day.

Its day 4, its shorter, need to stay focused on getting a win.. need it today.

  • Decided to go with the contact form, was easy enough apart from the fact that I could not figure out how to edit the tables for the default form, that’s a ‘nice to have’ so stuck to the ‘must have’ scope and extended the default form as required with custom fields. It was simple, took a bit of toying around but did not need to reach out or Google any how to’s. its a good win, was quick enough so decided to take on a couple of one more task.
  • #OpCleanup; decided am going to clean up all these modules that don’t work, err no uninstall button, its Google to the rescue, a little strange that to uninstall the modules I have to go here: /admin/modules/uninstall and there is no link to it from the extend page! may be I am missing something here. With another win and on a roll decided to look into this unexpected error I’ve been getting intermittently when installing contrib modules:
  • Found a page on D.O on the issue and responded to by a colleague! hello Eric! but the details’way too technical for my current knowhow or lack of! am going to wait till 19th Nov, assuming Dev Desktop will see an update the same day and reinstall Drupal 8 and see if that changes anything, failing that will be badgering some of my TA colleagues.
Was a washout! not enough hours in the day to fit everything! quick retro;
  • main menu,
  • footer menu,
  • social (Twitter) feed,
  • static content for pages,
  • font face
  • Favicon

Did not get to put in anymore than 2 hours over the week, got to >80% of my backlog, broke through last week’s blocker, got stuck on something allegedly trivial, that’s a good week! Looking forward to week 3, I’ll be jumping in font first! 

Peace Through Prosperity Open Transformation ProjectPeace Through Prosperity Open Transformation Project

End of week 2 this is where I am at, not bad!

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Nov 11 2015
Nov 11
teaser image for blog post

Launched in 2008 Drupal 6 has served a large base of sites for the past 7 years even with the more recent Drupal 7 launched in 2011.

As a provider of Drupal support and hosting services Ixis still look after a number of clients who are running the latest up to date Drupal 6 codebase. However, with the announcement of Drupal 8 launching on November 19th 2015 this starts the countdown to the end of the extended support policy - which is 3 months after the launch of Drupal 8. The final 3 months will only cover security updates - not functionality or bug fixes.

Drupal 6 Security Updates end on February 24th 2016

The 3 month window won't be long enough to allow upgrading of Drupal 6 sites to Drupal 8, especially as we'd always advise allowing a new major Drupal Core release to be tested by early adopters before upgrading and migrated your site to it.

What are the implications of this?

From Drupal.org

  • The security team will no longer provide support or Security Advisories for Drupal 6.
  • All Drupal 6 releases on project pages will be flagged as not supported.
  • At some point in the future update status may stop working for Drupal 6 sites.

From Ixis

  • We will continue to provide our support services to Drupal 6 sites and where necessary apply any security updates provided by 3rd parties.
  • We cannot guarantee your Drupal 6 site would not become vulnerable over the coming years as new attack vectors are discovered in web based applications and applied to old Drupal 6 sites.

What if I have a Drupal 6 site still?

If not already in progress, begin planning a site upgrade or rebuild. Web technologies have progressed a lot since 2008 which may mean reviewing how your Drupal 6 site works and what the business needs are - which may be better addressed in a more modern techniques thanks to the functionality of Drupal 8.

As with many of our long standing clients Ixis can assist with your journey from Drupal 6 to Drupal 8 with our in-house development team services. Now is the time to be making plans!

Any short term solutions?

  1. Reducing your sites functionality to content only would allow a quicker path to migrate to Drupal 8, and then as contrib modules are upgraded to 8.x re-introduce the functionality during 2016.
  2. Archive the site as static HTML pages - although this will remove interactive elements such as logins and comments.

What about upgrading to Drupal 7?

Depending on the timeframe and functionality required for site delivery Drupal 7 may still be the better option due to the sheer number of stable additional contributed module components available, such as Ecommerce.  At Ixis we're still developing Drupal 7 solutions for the next few months at least.

Speak to us

If you're unsure where the Drupal 6 support end of life announcement leaves you and your business website please do get in touch with us to discuss how Ixis can help in the short and long term. We're happy to chat!

Nov 05 2015
Nov 05

More a log than a guide, but you get the idea! Many a weeks before Day 1! started putting a backlog together, the site is for an Open Social Transformation project, its open sourcing the materials designed and developed for Peace Through Prosperity’s social transformation programs that have had epic results so far. The aim is to make the materials and processes available under a creative commons license for communities across the third rock to use and transform for the better, from the ground up.
  • Theme-Library-D8-Theme-install-failTheme-Library-D8-Theme-install-fail 25th Oct 2015 installed Acquia Dev Desktop and got cracking, first impressions; intuitive, a bit like WordPress thats a plus! the learning curve wont be as steep as I had suspected it might be.
  • Bartik looks dull and boring, decided to go on a Theme hunt.
  • Downloaded Zircon – installed, set as default, does not work,
  • Downloaded Adaptive – installed, needs something called AT Core, searched, and installed, set as default, does not work,
  • Back to google, found MAYO, looks nice, installed, does not work,
  • Am 30 mins into my hunt for a theme that looks good and works and am nearing to an OFT moment.
  • Another 5 mins and reached OFT moment.
  • Decided to go with Bartik, into settings and am determined to make this look nice, wasn’t that hard actually! 
  • But need to clean up my Theme library! this is what it looks like after 35 mins.
Drupal-8-engagement-manager-suite-building-guide-001Drupal-8-engagement-manager-suite-building-guide-001 Five minutes of fiddling about in Bartik’s settings and moving the Login Box to Footer 5 (not disabling it for now) this is what my home page looks like! Not bad for a newbie to Drupal… the fruits of less than an hour’s labour and it is responsive out of the box with zero effort!  OK that’s too much excitement for the day, going to quit while I am ahead and get back to it in a few days. A few days later… Decided to hit the deep end before creating my pages and static content, time to add some fancy Blocks, getting the @bringptp Twitter feed on the home page would be epic! The search began for a Twitter module for D8, two choices, Alex Finnarn’s Drupal-twitter-feed and the Twitter Module off D.O – hit a glitch with both, with the Finnarn’s Drupal-twitter-feed module off GIT the challenge became lack of documentation, once set up, had no way to figure out what to do with it as a newbie. With the Twitter Module installing the Entity API became a pain, first things first Entity API is part of D8 Core WTF! kept getting “entity-8.x-1.x-dev.tar.gz does not contain any .info.yml files error”,  looked into the error and got lost in the conversations about it on D.O! whoosh over my head! It was time to call in the big guns, time to reach out to Dakku for help figuring this out. As for the rest of today’s timebox will be getting the pages and content in shape to give the site some semblance of a site prior to diving into the Lingotek module. On reflection today was less frustrating, packed up when I hit a blocker, started finishing and stopped starting, am practising what I preach.  Met up with Dakku and made use of the lunch hour to get some help with the Twitter modules I installed and failed to get them working, turns out its the modules and not my lack of perseverance! Alex Finnarn’s Drupal-twitter-feed module doesn’t show up on the configurations page as the limited documentation suggests it should, so ditched that and moved to the Twitter Module. Got introduced to the issues queue for modules and how to find answers to issues I am having that others have faced, reported and found solutions to, turns out there is an issue with the module as reported on the issues queue, the module has a dependency on Entity API stated in the twitter.info.yml which shouldn’t be there, this dependency prevents the module being installed. Anyway decided I’ll get to Twitter feeds in a Block at a later date once its been patched – which by the way is under way. Dakku on it, submitted a patch that is pending review. With Twitter feeds out for the time being I got a short introduction to Drush and how to install modules using it, haven’t quite got my head around it yet but the fear of the Terminal is slowly giving way to possibilities of being able to use the command line to get sh*t done. Drupal-8-engagement-manager-suite-building-guide-003Drupal-8-engagement-manager-suite-building-guide-003 Back to building up my site, first things first the ‘read more’ link on the home page is getting real annoying, I need the entire content of my page displayed and not a snippet of it, late night IMing for help Dakku pointed me to ‘admin/config/system/site-information’ should have seen that! (mental note to explore more).  Menu links added, with the home page taking shape keen to get some play time with Blocks, a bit of toing and froing got to grips with creating custom blocks and wooHoo! rusty HTML knowledge’s coming back and is handy too. Added two custom blocks: Gofundme and a Vimeo widget blocks and it looks Epic! Still have some time to spare, decided to go social, and got pointed to the Social Media Links module by Dakku, looks awesome but came undone after installation! opened up the modules folder, had a look at the Readme file but when I go to ‘/admin/structure/block/manage/social_media_links/social-media-links/configure’ there is ‘no page found’ dang it! so close so close! must pack it in and get back to this in a couple of day.  Even if I say so my self am chuffed with what has been possible over 3-4 hours spread over a week, next up getting the Social Media Links module to work and then to Lingotek before I start exploring Organic Groups, which will have to be de-prioritised since Organic Groups Module is not ported to Drupal 8 as yet.

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Nov 01 2015
Nov 01


As a digital activist I want a forum that brings together individuals from private, public and the third sectors, to share ideas, address issues of waste, service improvements, development and innovation in the delivery of front line public services so that we can collectively work towards the betterment of public services.

Between the day job, give back and the fam little time remains for anything else, none other the DPSX initiative (now in its 4th year) has suffered because of it. After an epic turnout at Prague, completely forgetting to schedule it’s BoF in Amsterdam, I got in early on making it happen at DrupalCon Barcelona and it paid off, perhaps a gap year had built up an appetite for it.

DPSX-BoF-Dcon-Barcelona-02DPSX-BoF-Dcon-Barcelona-02 Anyhow the attendance was epic; we had four continents represented and discussions focused on issues faced by industry and the public sector in sourcing, adoption and innovation of open source content management systems. A huge thank you to the attendees:  Alex BlandfordChris SkeneKristoffer SoderlundJohasn Du BoisChris Hartigan,  Andrew HoppinSuchi GargHolger KreisTom Dean.

The news from Australia was both good and bad, whilst the Australian government is spearheading adoption with the GovCMS distribution, efforts are we were told loosing steam as the distribution in its current form is quite restrictive requiring significant customisation by individual departments adopting it. The question is why fork it? why not modularise it? having said that I am too far removed from the ground to comment on it, as such have reached out to my colleagues and the community in Australia to shed some light on the matter and shall keep update this post as and when I hear back from down under.

The news from home (UK) was a mixed bag too, whilst G-cloud is working for central government the word is it isn’t working so well for the local government (councils) and is being exploited by big corps for labour arbitrage. There were names mentioned (the usual suspects), large central gov contractors who outsource their wins to the smaller co’s in the eco-system which goes against premise for G-cloud to be set up in the first place.

Though there is truth in the big corps abusing G-cloud via labour arbitrage the SMEs have to share some of the blame too, there is a dearth of experienced Drupal resources and should the SMEs choose to they can set their own terms and put a dent in the exploitation we were so passionately informed of. Yes yes I hear you, they are not exactly a digital OPEC but then they are not powerless either.

The message here has to be ‘do more for all concerned’; GDS should do more to ensure local government (councils) have the train, skill sets and tools necessary to make the most of G-Cloud. Local government ought to conduct regular retrospectives on their success and failures using G-cloud or other means of sourcing and course correct their approach so that they can up-skill their procurement departments, cut unnecessary red tape and do more to encourage bidding and procurement from local SMEs.

As for curbing the big corps abusing their position and exploiting SMEs, GDS could improve monitoring down stream resourcing to ensure its not a marked up pass-through.

As for the challenges of contribs back to the community, central governments ought to make it mandatory for government departments to contribute back to the community (with exceptions for good reasons of course). To this end one single legislative change can transform the ecosystem from the ground up. A law for corps who provide frontline Public services, who as a service provider must make the data available for free (or a capped transaction fee) via standardised APIs to all actors in the ecosystem following the Open API principles. However it is clear that corporate service providers will need to be pushed towards Open Data principles and in making our data more widely available to prospective service providers to encourage innovation in the ecosystem.

As a tax payer I want companies who provide frontline public services to make the data they gather in the provision of such services available through Open APIs to other actors in the ecosystem, so that such actors can utilise that data to provide new and innovative services to the public.As a tax payer I want companies who provide frontline public services to make the data they gather in the provision of such services available through Open APIs to other actors in the ecosystem, so that such actors can utilise that data to provide new and innovative services to the public. Last but not the least and a regular topic of discussion at DPSX meetups is cross border service development and waste, as expected it was raised at the DCon Barca BoF too. The issues remain the same as they did a few years ago, as do the candidates options to addressing the challenges, some of them have been touched upon above, other’s I think we’ll keep for future meetups, which brings me to my new year’s resolution! more and regular DPSX meetups and that is going to be possible since a few folks from the community have agreed to get involved and share the load as and when need be, for that I’d like to thank Farez Rahman and Mark Taylor, thank you gentlemen.

DPSX-Register-now-EventBrite-2015DPSX-Register-now-EventBrite-2015 So the next meet up is scheduled for 13th January 2016 at Google Campus in London from 18:00 to 19:30, we don’t have any speakers as yet but that will change closer to the time, shall be reaching out to them lovely folks at GDS and DHUK and shall keep you posted of their likely attendance. In the mean time if Drupal and OS in the Public Sector is of interest to you please sign up for the meetup here and see you in the new year!

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Sep 22 2015
Sep 22

RNG has tagged numerous alpha releases and maintained stability with Drupal core. Because of this stability I will be accellerating to 1.0 by skipping beta and going straight to RC. However RC will not occur until the following requirements are satisfied:

Everything should line up for a RNG RC in October or November 2015.

Updated October 20, 2015: All requirements were satisfied, the first RNG release candidate was released on October 14th, 2015.

Cover photo (unmodified): Running gear of steam locomotive by Petar Milošević. License CC BY-SA 3.0

Jun 18 2015
Jun 18

Developer Soft Skills

One of my earliest jobs was customer service for a call center. I worked for many clients that all had training specific to their service. No matter the type of training, whether technical or customer oriented, soft skills were always a included. Margaret Rouse said, “Soft skills are personal attributes that enhance an individual’s interactions, career prospects and job performance. Unlike hard skills, which tend to be specific to a certain type of task or activity, soft skills are broadly applicable.”

In this blog series I will be discussing what I call “developer soft skills.” The hard skills in development are (among others) logic, languages, and structure. Developer soft skills are those that help a developer accomplish their tasks outside of that knowledge. I will be covering the following topics:

  • Online research
  • Troubleshooting
  • Enhancing/Customizing
  • Integrating
  • Architecting

Part 1: Online Research

One of the first skills a developer should master is online researching. This is an area with some controversy (which will be discussed later) but a necessary skill for learning about new technologies, expanding your knowledge, and solving problems.

One of the best reasons for research is continuous education. For many professions (such as the military, education and medical fields) continuing education is required to keep up on updated information, concepts, and procedures. As a developer, continuing to grow our skill set helps us develop better projects by using better code, better tools, and better methods.

Search engine queries

When researching a topic on the internet it usually involves using a search engine. Understanding how a search engine works and how to get to the results.There are two parts to how a search engine works. Part one is data collection and indexing. Part two is searching or querying that index. I will be focusing on how to write the best possible query, to learn more about how search collect and index data see this link. In order to write good queries we should understand how search engines respond to what we type into the search box. Early search results were rendered based on simple (by today’s standards) comparison of search terms to indexed page word usage and boolean logic. Since then search engines have started to use natural language queries.

So we can get better results by using this to our advantage. If I wanted to research how to make a calendar with the Java programming language. instead of searching for keywords and distinct ideas “java -script calendar” by them selves; use natural language to include phraseology and context in our queries: “how can I make a calendar with java”. The first result from the keyword search returns a reference to the Java Calendar class. The first result from the second query return example code on writing a calendar in Java. The better the query the better the results.

Search result inspection

Once we have the right query we can then turn our attention to the results. One of the first things I do is limit the results to a date range. This prevents results from the previous decade (or earlier) to be displayed with more recent and applicable ones. Another way to focus our search is to limit the site that the search takes place on. If we know we want to search for a jQuery function search jquery.com.

date_search

Once we have filtered our results, it’s time for further inspection. When viewing a results page, the first thing I look for is the context of the article or post. Does the author and/or site have a lot of ads? This can sometimes mean that the site is more about making money then providing good answers. Does the page have links or other references to related topic or ideas? This can show if the author is knowledgeable in the subject matter.

The controversy

Earlier I mentioned online researching can be a controversial topic. One of the points of controversy is discussed in Scott Hanselman’s blog post, Am I really a developer or just a good googler? While I agree with his major point, that researching bad code can be dangerous, I contend that using a search engine can produce good results and learning opportunities.

Almost anytime you search for any programming topic, one site or group of sites is predominant in almost every result: Stack Overflow or the Stack Exchange group of sites. Several articles have been written about reasons not to use, consequence of using and why some developers no longer use Stack Overflow. Using Stack Overflow will not solve all your problems or make you a better developer.

Again, these arguments make some good points. But I think that using Stack Overflow correctly, just like good use of search engines, can produce good results. Using a Stack Exchange site comes with the benefit of community. These sites have leveraged Stack Exchange Q&A methodology for their specific topic or technology and can be a great resource on how to solve a problem within the bounds of that community. One of my development mentors told me that there were thousands of ways to solve a programming problem and usually several wrong ones. The key is to not do one of the wrong ones and try to find one of the best ones. Searching within a Stack exchange site for answers can highlight the wrong ones but also provide the ones that work best in that system.

Here is an example of a Stack Overflow Drupal community response that came up when I searched for: “drupal create term programmatically.”

stack_overflow

This response is correct, but if you look at the link provided, you will see this is for Drupal 6. If you were looking for how to do this in Drupal 7, for instance, the answer provided would not be correct. We could have improved our results by adding “Drupal 7? to our query. But most important is to keep in mind that sites like Stack Overflow, or other community sites such as php.net include a mix of user generated responses. Meaning anyone can respond without being vetted.

Keep going

The best piece of advice I can offer for the arguments against using online search results and Stack Overflow is: “This is not the end.” Keep going past the result and research the answer. Don’t just copy and paste the code. Don’t just believe the top rated answer or blog post. Click the references sited, search the function or api calls that are in the answer, and make the research a part of your knowledge. And then give back by writing about your article or posting your own answers. Answering questions can sometimes be just as powerful a learning tool as searching for them.

In the end, anything you find through search, blog, and code sites should be considered a suggestion as one way of solving a problem – not necessarily the solution to your concern.

In the next post I will discuss a good use case for Stack Exchange sites, Developer Soft Skills Part 2: Troubleshooting.

Subscribe to our newsletter to keep up with new projects and blogs from the Phase2 team!

Jun 16 2015
Jun 16

After 5 months of development, RNG is ready for its first alpha release. A milestone where there are no major issues, and schema is not anticipated to change leading up until v1.0.

RNG is a Drupal 8 module implementing a core toolset for allowing users to register for events. An event can be a presentation at a conference, a meetup, a class. If you need a way to associate people with a Drupal entity, take a look at RNG.

Core features of RNG:

  • Any entity type — designate any bundle (e.g node type) as an event type.
  • Self and proxy registration — users can register themselves or other identities to the event.
  • Multiple registrants — registrations can associate multiple identities.
  • Messaging — messages, such as email, can be sent to registrants. Messages have token support, allowing you to recycle field values from the related event, identity, and registration. Messages can be timed, or sent when a registration is created.
  • Additional identities — the Identity module allows you to register non-users. It is modeled like an address book, where contacts are added, and then made available as an option on the registration form.

Theres still a few things that will make it in before 1.0 final. Including improved Views integration, and improved/full test coverage.

I work on RNG in my own time. If you want to help out, don't hesitate in posting in the issue queue or contacting me directly.

Need help getting setup? See Quick Start.

Download the module on drupal.org.

Cover photo: Seedling by sjg. License CC BY-NC 2.0

Mar 20 2015
Mar 20

Today is an exciting day for the Drupal community! Collectively, we’re all moving a few steps closer to a full release of Drupal 8 with the help of a program called Drupal 8 Accelerate. This is a pilot program from the Drupal Association designed to put $250,000 of community funds towards eliminating the last 50 critical issues between us and release.

The Drupal Association has been an incredible leader in the effort to release Drupal 8, pledging to set aside $62,500 to match every dollar donated to the provide Drupal 8 Acceleration Grants.

What’s the latest with Drupal 8 Accelerate?

But we knew we could do even more to turbocharge this project. Today we are announcing that D8 Accelerate is now getting a huge boost from seven anchor sponsors, who have pledged to “match the match,” amplifying every donation made and accelerating the community’s investment in Drupal 8.

Phase2, Acquia, Appnovation, Lullabot, Palantir, PreviousNext, and Wunderkraut have collectively pledged another $62,500 to match the Drupal Association’s matches of community donations. This is an all-out, everyone-in community effort to move D8 from beta to release. Our goal is to bring the total to $250,000 available for grants by September. We are now more than half way there.

drupal-relay_1

Why should we all want Drupal 8 to succeed?

The answer is simple: D8 will empower us to use Drupal the way many of us have wanted to for a long time. D8 improves the API layer, multi-lingual capabilities, theming and the editor experience. It also makes is much more powerful for developers (which matters a lot to us at Phase2).

Historically, it has been a challenge to integrate new libraries or different front-end elements without a lot of leg work. Imagine, for example, how the availability of Twig theming will enhance your projects. Or how flexible implementations can be with dependencies on meaningful external software integrated through Symfony routing. We will even be able to more seamlessly incorporate mobile apps into the digital strategies we develop, correcting one of the main weak points of previous Drupal releases.

Put simply, Drupal 8 is a win for our collective clients, and therefore it is a win for all of us.

Phase2 & Drupal 8

At Phase2, we want Drupal 8 to succeed because our clients have increasingly big needs and major challenges, and we believe that Drupal 8 is moving in the direction to address those. For that reason, we’ve made investing in Drupal 8 a priority, not only by way of the Drupal 8 Accelerate program, but also in the form of contributed code and shared knowledge gleaned from major enterprise Drupal 8 implementations.

Taking on early Drupal 8 implementations enables us to commit our people to the D8 cause, while directly supporting our client’s mission. It also provides us with a group of advanced scouts to report back from the front lines and develop training for the rest of our team.

Principle among these scouts was Software Architect Jonathan Hedstrom, whose contributions to D8 include Drush support, core patch reviewing, testing and re-rolling, writing tests, modules upgrades (Redis), and more. In addition to Jonathan, Senior Developer Brad Wade made important front-end contributions, while Software Architect Mike Potter has been a significant part of Features development.

We’ll be sharing a lot of what we learned from our D8 work so far at DrupalCon Los Angeles, so stay tuned for our session announcements next!

 An all-out, everyone-in effort

It took the whole Drupal community – including individuals, companies, the Drupal Association – to get D8 to the place it is now. We are honored to have contributed alongside everyone involved. It has certainly been a heavy lift for many community members, so to each of these people and organizations, we say thank you. The success of Drupal 8 is the most important priority of our community.

Screen Shot 2014-09-04 at 11.14.45 AM

However, Drupal 8 still needs a strong push to get over the finish line. So we must ask one more time for the support of our fellow Drupalers. We all have a major stake in the success of the project, and everyone can play an instrumental role getting it out the door. Even the smallest donation makes a difference when every dollar you donate is now matched, compounding your impact. You can read more about how the funds actually support the grant program to achieve the work on the Drupal Association D8 Accelerate page.

If you would like to donate, please visit the D8 Accelerate Fundraising site and please consider using my profile as a way to easily make your contribution so we can start enjoying those launch parties!

Mar 01 2015
Mar 01

DCLondon-2015-01DCLondon-2015-01 #DCLondon 2015 was nothing short of Epic, Drupal Camp London has in its own right become a mini-Con, with community members flying in from not only across Europe but the US, India, Australia and New Zealand it is hard to call it just a London camp!

London is the centre of the multiverse!
Drupal Camp London 2015Drupal Camp London 2015 It was awesome catching up with old friends, some new ones and finding an engaging audience for my session on using Empathy maps, content touch point analysis to develop a robust content strategy.

Bummed about not being able to catchup with everyone though!!

I’d like to reiterate my two asks from the community this March:

1) Like, Follow and spread the word on Bringing Peace Through Prosperity, it goes hand in glove with our activist nature and desire to make this rock a better place today, tomorrow and beyond.

2) Drupal Camp Tunis needs our support to bring their local community into the wider fold, the organisers at DCTunis are looking for speakers and support.

And a HUGE thank you to everyone who attended my session…

See y’all at the next Camp!

One more option to look on her packing at it levitra vardenafil it of course to take not so simply because a form another and there is a wish to hold in hand her not so strongly. You can carry by me on a wide field.

Mar 01 2015
dpi
Mar 01

RNG is an event management module for Drupal 8 created in the spirit of Entity Registration (Drupal 7) and Signup (Drupal 6). Users can create registrations for events, and event managers can manage these registrations.

Updated April 6th, 2016

This is a quick guide to getting RNG set up.

RNG

Feb 26 2015
Feb 26

‹�]�r�’�-U�`z#’k/’%�”(�|I�N�”=��X�H�5œ™�E4��]�,~��‘”L9��s��‰�\�F��k�y������z&���;�>�cY��c��™8x‹WJ�3���&<�O5�[?>�Q��”��–U�x�T�p�Š–*>ب�1�;��0z�|{B…2�˴,�Jo��ƒ_3•HaOe�dP���|t�_�Ԡv�yDIM؁Ÿ(�“L��tme�‹�•�‰�N�Fi(=�D�Bq��n,v��}�s��n�w„t�I N�� |�‡8����‘��q�$'g�ŸE�qm���*�TQ���~Jg����4‰��—���Y�F���^K� f��c™��qG��}��…ˆ”7�…Q0351��xP›&I��t&�p��I�����z��E�8Yx*�*%‹"K��c�qM�”��A ]^�9Ÿ���H�Q–��+W=i�i�9�25G&����Du&��h$cup������7=��ǧ�O�ŸW�Ng�����g��B�>>���_Ÿ��q"��hk^�����2…*“Cz‰Š|�?�@†•��Dq|�Yd ����Zk‡���*��ʬ�e��‰��ip$~P��l��Q��<���z�$˜�0��[t�6U�%�w;o��p��FVB X��=�JK2�’��2�x�9�‰2w�›y{8�,x瞩„d�v�F3��ȫ�5co:o:q{N�M‡�k�C�7��s���p�M�֪�)Tk‡>�k-f���kp6—.S]��7�2\Ÿ�2ZzsW�� ܵg�‡�7���m�֮hrom��>ˣ![�–��˜��!›�K�ƒQێ`O�3O�X4j��!�Z����D%O�_�Ovv�o�ڮSkE*I#���qڀ�9�5œ6y֠�$� ��P 4t��Š���8�\�A0cONjƒ�@R�ŒH�,‰0�q̞q= �����?h�<�����a��mu›-��OaE}��l{�Ÿ$�“=���oB�h��Z�;ƒ�C�}N#LT�ƒ���5�d��m6�wzW�L� 25��<��$1�V[#j��‹/�����F� h�‰V�˜���O���4���8nMˆr�Œcwz��a~�`’”)��ݼO_��Dƒ;=�E�H�“p� Wœ��r�.��šikڤyQ��ƤJ�B���Gm�8�x’n0��G�մF -?�h��2��š���š-��,9;“�G‰$‘�”5j�o�›�v5‡�‹��?Q�V‰yLV�$�+4t�{rFe����jB�˜3z����ǫָ]š�T���������Œ�‚�A��[�E/�T�ټjh[�r;%i]c�šd �Nf���2�>��}�;�†E‹_™AFǍ�W�\Ÿf��ƒ�8K?�Q1��ƒ�œ�V<•`k]�T‘K�‹�šU384Z“�9q��Šv�p9“�|—gIϝ���m���™DAJ8r•Ÿ�‰�r��� ��^D/u E�m��@!N�B��Ɓ@’rƝ4�^�•�,�-l�{��z����z�����M�T‡ ֫�`…�w* !†��2�RŒB�1„���9gu�����2—7:�"ŠŠ�—ݸ= ‚‰�B�Fb"…HE,T�Y_�Ygš_�j�f�•w��*Z˜_™w�{��n�‚}�v�™;‰`-��{9ˣ�ў����a„Nr�P'�� [F}�ɯ�Ÿ�G�N��>{z۠�h,��7*u�*NֵZ�֭o�ؐT‰@› tNDy�…‘��›>�ϧJ�h8�ڍ f�k-j‚X”B�%X^�h~&SeED��˜4PaF�J*$;�6�‡��\–‘�‹>ůBw��9Fx6e2]l�b�{LW#�‚�,���• |��o���`�RNa��u�F…ƒ�ƒ������‚5M”��n‘}W!z�s����P�mW‰F�(H�$� ��–��M•�c?�[email protected]���b+v����1y�#q�aˆv�x�Œj…(�y�p��0�Ey��†�‹~�Ÿ��:ƒ�2�H…����q�@��6�Q‘�EŮ�K�����…8Ÿ� ��*~V�q�^\�‰Z�_MQd��9���“��秿mJx�_�lj�(��mZ�)J�F���5M�Ш;�%a‚7�dX�y:���Rš�FqqR�$cJ-F‚s�v:�.���][�‡���n�”����(\oŠ �*����„~‚›(�J�~u���q.�‘�&�)–^‡3�=�42�c˜c�uw:�…����y��„5�‚�I;�*�ֿ���‚c��†�‚�ѥd�"�|e'0�T�Bu&`…��ˆ‰Œ�h�n�����6c��I�`�&�^9`��?Pd��ƒ���k�e�”�ˆ�����œ]Q�����}@b�˜���=Ǡ �ƒB�_�A?\Ǣ�)Kתj‘�p�'��ŒD2�{/��BG���‘Œ�†��PKS�7�MŠ� •a:� �8th$a|"�O R†�Œ—W�™ei'pr‡�?9–�“š�6�“����†��3�e=�-zV�'/��v�m���(��K_�Z�9��ˆׁ}"�ZT�LVL ��”�*p�<"Q����8b�:3�‡(?|�C:�[�-†a��Œ��nji��cP��߭ �]g.��™MI-=�2:&N�‘�0`:"�#pkO)�3 �H�Ǟ)a}�4�8j^���“3&~���\��ô“�U�=X mb�[M”�4p0�l�L*NG3� –�j��n–r)�TU�wH��}�́�mE‡}�TG�;‘Z��Dػ[email protected]�)}��Y64�nhԭ‘EXO��‰�F!\T"DF.���|�yJ!w1=–š#f�R�Q�$66B'?��h��U =2•CX�™�'‹��c�6�,�BX�h�mE�D‡X��r܁��l���‡C��Im”MVf–96%��3D��La��Œ��R3›�.�e�)� �ɭ� š�Š�T�:e}`w��#����i��o�\[�N٩K�‹ �H�j';p•�‘���•a�������n��-�p �š�/�)��<*q��pY�Š����� ��:‚QcX‘›—<…A› �A(�L��A,�> MT™�I-,�"�w˜b�C9�JTgi‰��7���’•�‰œHc� )_���šHY���(�ƒ`����&•��rK�i� 0X�3��Vk��m/vM�恱h���P› �pŸ͎���›��V�f��‚�F–|żU^>]F?)裂��5ŠRrt�-– �)=��aZ��D�J�V�3›V��u�%‡/%?œF�9��p%q)�6��oW�� ™‰˜X�O�*NE†7��2�W�+�›‘%#��–�]Œ��Š[K~�]�Dc�Vu'G�ͪϝI�9��r�'�“�I��›:K�t���ƒ:� �k�� ƒ�U�qx�[email protected]�thƒ—�m��~M��ƒ=s �/>�����9�z�‡�h�^�}(Š�<�„�zŒ�ͬ�2F���’�m��-Wf�J��“�N`��+k•›����igΫ™�Y�„�e4��2†#8gX���Nš›++�Z��eM���šeO�)2�Œ�)�&`[��"�#э=9“#I'S—™�—^™���Wxc�CC�1‚C�h˜P R‚�Sr�܍)���†�}�… �K'�.��+�j[s��\8�2T��d�sWK�‰�Ÿ�ˆ��“����������›><Š[���YL‚RJd|�}„>Ho,$™`��ԝq�œp�ˆ%诧LQ�!B{�#�Fu�����{/�J�b����� p%^��yh(�1E•d����Pn��’3�‚Ql��›����\Š�ݤ �i4��bKZ#�wD�$�”�g!aD�(�$���� �H�c[R'�(H'S‹ ���‚�/A͐6�{k��BU,A7�By[<3FŠz*…���“j‰��`BN�‹�B�5L#6Q�Ÿ(���A›Z•hGB�A%zվ�SŠ PC���HAi�7�)�„f�|j&�.wK�,˜�v�sfB�,c7O���V)@“8‰�w ��ߧ•��Xrj�"™XeIX,k�™�[�����–E*��%+�r�dZЬ�D�†��3DKj��’�ǁ,��y�Pmst pP‘h"Lg��Œ�x!�.„5����b�_1��DG?(�z|4$“�i��l—d\[‚��\�ZjSšXš(m~�m�Q��;K��tŒ6�P�’O�F\��’�Z5(j6���/0 Sq:�(���G/Xʳ…�����!�]�4�#]˜����x�RҦ�_���U�!d�,��h�9�\]��t����/bV�J춬�Ÿ?�8)��3 �[*�[�nW�R/q=��H0�œ”g‚d���o<+H�6P™����h��z(2“�V���…9��– �D'›ivA/bw„–��j�S�H�Aa9�wŒ!A�Ӑ��7ci=�dB4��5/„œ<�B j?�ˆ…8� �[email protected]`ˆ�i$0�JG�d]x–C[Yš˜YjA��—�8b\Ÿci“b�ר� N�S�‡kš���^ŠҮO�ˆ�‰†]�[email protected]…�9Š�,�…�‰m–‘�œ$/y��ˆQ�k��-�J^ a�;���2���‚| K!�fb�—l�1�ȭq4�‡�$r��cƒ9OIְ��d�ŠЦn �NSH�Œ�T^�2�…�vH�>T6$e�”†���b�]*mu���Y�—z��'�S_�E<�@›�!6[P‡‘R�$š��%dŒ{ lŠ�PmE�����p$AŒ�˜��ƒ�>5K /�|��H�Œ]Q9�*�V]mƒ�����<��ݻ_„V�R E{„��o�V��On!�o���U2]���+�™�6a=��(�\ˀ+W�U%�!R#ڷͷ[��Ÿ�ixƦ��H�u���� �[email protected]~k&�Az� ši �g“mBfa��3�`��“0LfհǤ#“mL�#��ƽ�#[œ�w„�%;1 SLw�œ�skq��?˜J% ���u��^�$��pe�-� ���a7GŠdŒ˜G{]H��,z™Œ'e��[email protected]"�R(���OOŸ˜hŠlŒ�� �oœfO_,B�9- S'��—:�N�<.…'����'�#����š��`Q/rP��’�i‘��š��„"��w�wiB`�lPYw�E`D�; p���A“���ҍU�nlŠŸiG����H�1���˜���)�K�� �~#�Ir�1�š ���4' šL��oa4��'�[email protected]��AA�7“`6�o��/c|��P6�–�b/Hˆ�™�tp��!P„ˆtŸ‚Ya�)x ’��•;&BŸд‘xv�/�f…–�˜� �%W;U�‹i;�ӳ˜�KŠ��1�UT�e����7‘B�Q�‡ ]i`��n�X�l�{��L�Mr��m�͡c��"_�ud‘‰™��6e�$r’M^��_GW��D�—�6J;_�›(�B��lY�o);sZ����zM�y-�R��˜�n‹u}���ߍ���Y��umW6o�7xNEx���u�Ru�n/�Z~J��ña�“ &妫�r��]� &ͧ�n�E���G]���Ĵy�W�_@ƒ��dE6�k�b���*”x—n 9F(†fi��:�-�n)k��2oM}�\A…��[S_c��”u&š7r�4r�’�[���Uʼi��a����}�xl%0��6g ^)ŠT����[~Y�tp"�H1��dbGƒš���(��0™sN�‘��˜S��›�+‡�ж�n�f9�)�{�kš�Xːr�s�z�p�S,\g'b|`a—™���—�5�-ˆg�-Kg��wv�[O^™�~>��‡��9��ˆ�������Q‰4��9l������{–†|’’N]���[w�š�$ǝ��G��V�$��—ͩ- š•�›S�{�p�eŸV+y'gSZa_�B�ѸX�E��4`�}[��Jq—��1>Yk��†��n��:lP+3vT;y���oN�h��3��sKŸ�^�+'•v�‘œ��"��o�Ԭ��G#�?r�߿�{p�s����H�Ÿ“�S|H�E�|Ի��"�{�F�Ÿ�šI��tNœ�C�#�TNV8NFyRVj�‡�3�8+�_‡���K��œI���G���lt�%†,��%/�=y�5��K‚{����Y�� �6�w8p`,u2_��wn���†Li�2û;�{�u0–�1���‘������g�>���F���wyS"��|�w�����IA�Fš†r�p.�zjc��*�>}}M����Hdw�ܧ�Ÿ��M9�X�B�9eP�����$jL“�8|&‹H��?†F/��&j���œ+3'��ƒ1����S�q”Ÿ�˜��–^�<-�4sŸ—”‰`)��lQ\��j���Ws����a�R��^Z �œ[email protected]™����†[email protected]��+œ�}™�EQ�S�„�2�ȧ1-—�8��m��rɫ4_�|e6�(, R‡��:��"�;�"‚����T��ݬG”„#'������—@˜e|Z��[�~/h��|� )��:���o�:��w����b�…‰=•dq�|:&†汸 �{�=8�—)|�]�I�m}EjFr��KQ{��6��xr����O�� `�…’>Œ4��+�z�“��\�e3r0�wMk�g“�P��x��H\�X�”9s?(:㍲��—�}̺ؐ��s}�U�C)kȼ���œ��~�D�{=�"R�—��ӭ� >���Vz�C0”~��Y,�š…�ѫ[4��?}���dҧ�Œծ@j��ͭ_"�t'�(H’`�‰•G�l��q�Ȣ"dMJ�I��Œ D�揮>–�aARc•‚�h�Բ��3����*`���/��oM���k��”[=�de:4A�Š~��Ÿ�k����:8ˆˆ�3t}›?ˬ�^�� ��*_�U�7�•�y����΢1}�x����i‹��n�Nš�A���o7�!e�+ƒAvk � ejOe<�L*���x��Aw� }ne�dP�Q���S&�fL��V�~™zNNG7��–YJ”��@t~Q�W��ä�t4T�'�Q�@ޫ,u‹�[M�y����] ��‚�P5�Y {�F<7;�9�!N)�Y��3�4�D}‡�•�:�#!���ŸC���h�“@_���—gm] …�����_^�p��+���\����c�WN]܁�'“Œ��ƒ>2#P$�‡�v��,�T?:”j��Tmx���”M��s�%t��ɬ�p"�SX"���B��f�Yix…� ‰�„^�zBWye/†{-&^`�Xn<�jKW��‹\�"�}T!�l�–~k>_1V-“��3�™{�‚����ƒrۤ }�/o��Q�„J��-sx9?�q�]�vg�•lL��[�Gy�#[��e�W��<�Eƒ\CJ�r�!_"R�1��1s����<^•�[email protected]��?ú�:A�W��|Yv� Cb�6mQŸiŠ�Vi6�“'…�•���� �5��<��0Qu��2Œ=Ͷ�T |�z�›W��–z^\����5��Š���Z��[� $�š�,–P–�5�…Œ�-`�iqj��A��.�?���=�Ym:…��M��_H‚˜?^�iƒ��zׯ�����a�~=ƒ��6���V�O�V��z�W�o›�ͱ)<�0P*z� ]�X4 4q�W�q‡n2�›���J<]o�6_�!�b�>„�m?8|(b�vu��� *�D�Х �*��:KCY\B˜�'��o��‹�A��Ao߬�1�`�F›M1��†”�0&Oѣk

Jan 06 2015
Jan 06
teaser image for blog post

It was an exciting and busy year here at Ixis in 2014 as we continued to build our portfolio of Drupal clients

Highlights have included celebrating our tenth birthday and building on and growing the team’s expertise which has allowed the company to win more clients across a variety of sectors. We also celebrated one of our best financial quarter since Ixis was founded in 2004. 

Having won a string of new clients last year including national consultancies, local authorities and leading charities, our focus in 2015 will be on expanding our reach within these sectors. We are also developing plans to collaborate with our clients to deliver long term value which increasingly means investing sensibly in research and development.

The G-Cloud has had a big impact on our business so this will still remain central to our growth strategy. We also truly value retaining our clients and this of course will remain one of our biggest priorities as laid out in our core strengths.

This year, we want to continue to grow our business whilst maintaining one of the strongest and most diverse Drupal specific portfolios in the UK. Here’s to an exciting and prosperous year to all.

Interested in Ixis? You can find out what it’s like working with us here.

Oct 25 2014
Oct 25
teaser image for blog post

We are delighted to be working with the British Council on a new Drupal hosting and infrastructure support project. The British Council are valued clients, and we have worked with them for more than 6 years managing both the global suite of 150 country sites, and the prestigious suite of Drupal teaching and learning sites.

We will be working to to create four individual platforms for hosting key Drupal websites on, moving away from just one main infrastructure, to improve resilience, efficiency and increase availability to the sites which generate more than 35 million page impressions per month and are used by more than 65 million people each year alone.

Will also continue to provide 24/7 Drupal website support to the sites which include Learn English, Teaching English and Premier Skills English.

Martin Heineberg, websites and media coordinator for the British Council, said: “Having worked with Ixis for more than six years, we knew we could rely on them to provide the right solution for hosting the websites. As Drupal hosting and support experts, they are always quick to respond and resolve any rare instances involving technical issues.”

We are looking forward to getting started with this hosting and support project, which will be one of the largest Drupal infrastructures in the UK.

Read more at on the Prolific North Website

Oct 10 2014
Oct 10
teaser image for blog post

I'm Andy, a developer at Ixis and having just settled back in after my first DrupalCon I thought I’d wrap up my thoughts after attending the annual European conference for the first time.

Initially - wow - DrupalCon is big! I’ve only been to some smaller PHP conferences so to see over 2000 people in one place was quite something. What struck me was how well it was organised - everything was on time with very few technical hiccups. I found the number of sessions quite overwhelming - there was so much to choose from, so having the videos of the sessions online with in an hour or so after it finished was really helpful. I’m still ploughing through the ones I’m interested in.

Just a quick note on my favourite session: "Field API is dead. Long live Entity Field API!". It looks like the Field API has really grown up and using some solid OO practices. I think it solves a lot of Drupal-isms developers have had to work with in the past - this session seemed really well received with lots of applause. I really am excited about working with Drupal 8.

It was also the first time for Peter our project manager:

Still under the thousands of impressions what I've received during Drupal con :-) The event was absolutely magnificent, meaningful and enjoyable at the same time. The organisers appeared very keen to provide a high level of technical, catering and professionalism to the event.

What I especially enjoyed was that I could meet the faces of the Drupal community: developers, project managers, company owners, freelancers, people who are working on small to large scale projects. The diversity of the community was amazing. The socials which were organised besides the main event were great as well. I think the greatest challenge on the event was to find enough time to sleep and rest.

I had a number of favourite sessions and it's hard to pick just one, so try to my best and pick two:

How to sell Agile - Vesa Palmu  has really good entertainment skills. It was a well built presentation about Agile's advantages, pitfalls and some honest advice about the limitation of the methods.   

Part 2: Train Wrecks & Ugly Baby Client Meetings - Susan Rust's presentation was more like a discussion about everyday challenges of a project manager, rather then a real presentation, but definitely useful.

So altogether if you haven't been to a DrupalCon we have to tell you it was worth it. Consider next year's European one in Barcelona.

Sep 05 2014
Sep 05
teaser image for blog post

With the 2014 European Drupal conference fast approaching, the Ixis team members attending this year have scoured the schedule for their must see see sessions this year, and why.

For the Developers

Content Staging in Drupal 8 (Wednesday 10:45) - moving content about from dev to production has always been a huge pain in Drupal, so hopefully we'll get a chance to see how this might work in Drupal 8 and finally put an end to the question of when and where the client should start adding their conent during the development phase.

Drupal's PHP Component Future (Wednesday 14:15) - we're already using and developing modules for our work with Codeception, so we would benefit from learning how this might apply to Drupal 8, or even 9.

A Decoupled Drupal with Silex (Thursday 14:15) - decoupling Drupal from the front end has been a topic for a few years now. Learn from others who have jumped on early and ironed out the development problems. Relevant to Drupal 7and 8.

Drupal 8 CMI on Managed Workflow (Wednesday 13:00) - as projects get more complex the pain of the Features module becomes well known, CMI holds much hope for the future of automated repeatable builds.

Future-Proof your Drupal 7 site (Wednesday 14:15) - Until Drupal 8 is out and under some real world use we can ensure our Drupal 7 development choices make the upgrade path less painful. We'll see what's in Drupal 8 and how that maps back to the available Drupal 7 modules that are currenly available.

Twig and the new Drupal 8 Theme System (Tuesday 10:45) as we all know Drupal 8 will be using a new theme system called Twig. This session should provide an insight into what to expect from a support point of view.

For Business Owners / Project Managers

Project Train Wrecks (Wednesday 14:15) promises to be an insight from other agencies on the problems faced and solutions to keep projects running smoothly.

The Myth of the Meerkat: Organising Self-Organising Teams (Tuesday 13:00) finding the balance between processes and control when working on a project as a team in order to get things done. Leaving everybody to get on with it rarely works.

There's plenty more to attend during the week to keep everybodies minds happy - the countdown to September 29th begins, and tickets are still available at the slightly discounted rate until September 16th.

Aug 15 2014
Aug 15
teaser image for blog post

We are 10 today (ok strictly tomorrow but it's the weekend!)  We're all off to Centre Parcs over the bank holiday weekend to celebrate, and thought it was good time to reflect on some of the highlights and changes over the previous ten years.

  • It all started from small beginnings with a £1000 grant from the now defunct Business Link.  In their wisdom they decided to issue the grant as physical £100 cheques every few weeks which we found amusing at the time.  Myself and Mike bootstrapped the rest from our own pockets and became profitable quickly having no loans or overdraft, which is still true to this day. 
  • Strategy - In the early years whilst predominantly dealing with Drupal, we'd still occassionally work with other frameworks or custom PHP.   After regretting doing this on every single project, we made the decision to work exclusively with Drupal.  We also decided we would not become a full service 'jack of all trades' agency offering the likes of creative services or SEO.  This allowed us to become truely focused as a technical Drupal agency providing primarily Drupal hosting, support and development, generally with large public and private sector organisations.    
  • We were one of the first companies to be selected as a G-cloud supplier, and one of only 3 Drupal companies who joined in the first round.  We were an early advocate and have been vocal about the merits of the framework, and have seen a huge change in public sector procurement in a short space of time.  We even get to compete with (and win work from) the big service integrators.
  • We moved office for the third time in 2012, to a new 2000 sq foot office.  The intention was this space would comfortably allow for expansion, but we've managed to fill in just over 2 years (RIP our beloved pool table).  We have always had an office and whilst we agree with some of the benefits being distributed gives, I still think in hindsight this was the right decision given the services we provide.  After phasing in remote working more frequently, we sent an open survey to the team and the majority liked working in the office and wanted to be there!
  • Ixis acquired Leafish in 2012,  Dylan and Paul have been instrumental in taking over and leading our infrastructure and development departments respectively.
  • Community - We have sponsored DrupalCon and our staff have been heavily involved in organising local meetups and DrupalCamps.  We've tried to attend most European DrupalCons over the past few years and it has been great to see the community grow over time.   We've always tried to make an effort with schwag and our stress balls have gone down well, going through three iterations over the years.  We've evolved this and produced something different this year, check them out on our twitter account @ixisit later today!
  • Contributions - Ixis have provided patch contributions to Drupal Core and numerous popular modules over the years, such as Google Analytics, Cookie Control and EdgeCast
  • Colloboration - We've always worked and partnered with other agencies outside our core area of expertise, and as such have built a good network of other companies who we refer work to and from.  We like the way the community colloboration extends to various other parts of the business, so competitors end up working together and discussing things like how they sell to a certain customer base or architect a system.  In other sectors, competing companies wouldn't dream of sharing their 'secrets'.
  • Growth - Ixis have always aimed for sustainable long term growth, and the majority of our clients have now been working with us for many years as we've ensured we retention is high.  The business is now stable with a high percent of re-occuring revenue, and in the last few consecutive years we have doubled staff numbers to nearly 20 and increased turnover substantially.  Growing in this sustainable fashion has also allowed us to ensure we maintained quality and looked after our long standing clients.
  • Continual improvement - We have made improvements to the business every year and will continue to do so.   Various parts of the business have evolved and adapted to suit the market and the needs of our clients, from our infrastructure to our staff.   We've also consciously moved away from being a lifestyle business predominently made up of techies, by expanding with financial, sales and operational roles.      

We would like to extend a huge thanks to Drupal and the community for making all of this possible.  We also couldn't have done this without our clients or the staff that work with us, so a big thank you to our clients and our team for allowing us to make it this far, and for the enjoyable rollercoaster that is building a service based company.   

We wouldn't claim any of the above has been easy with every year of growth and change bringing new challenges (and increasing grey hairs!)  We've learnt from our mistakes and with the benefit of hindsight we'd no doubt do some things differently.       

We've had the pleasure of working on a really diverse range of projects, with everything from local historic club The Hacienda through to charities like Epilepsy Action and global organisations such as the British Council.

Thank you also must go to those companies who have helped us along the journey including branding, marketing, strategy and PR, technical services and mentoring (you know who you are!)

It's a slightly scary thought that after starting Ixis in our early twenties we've been doing this for over a third of our lives, who knows what the next few will hold!  We are looking forward to the next chapters and the future of Drupal...here's to Drupal 8! 

Jul 16 2014
Jul 16
teaser image for blog post

Since we integrated the EdgeCast CDN for one of our clients, and released a related EdgeCast Drupal module we have been encouraging more and more clients to consider a CDN layer to accelerate performance to multiple geographic locations and maintain an excellent uptime even during site maintenance periods.

A recent international client who is running many domains with federated content using the Domain module needed to make use of the content delivery network to improve performance and resiliance for their sites.

The use of the Domain module created a problem with the purge process employed in the EdgeCast v1.x module. As with most of the cache purging modules available for Drupal it sent each URL individually and waited for confirmation back to say it the request had been successful.

With a large multi domain site this multiplied the page load time upon submitting a node edit form to the point of a PHP timeout and Ngnix HTTP 500 errors. Increasing the timeouts was a short term fix, but it still meant content editors were slowed down waiting for forms to submit.

There was also another effect cause by external feed aggregation which created nodes, which in turn triggered URL purge requests, and slowed down each node creation step.

We toyed with the idea of using a Drupal batch queue to process the purge requests during the regular cron call but this delayed the refreshing of content pages far too long for the content editors.

We settled on what appears to be the little used Multi Curl facility. This allowed us to build up an array of all the URLs using the Expire module and then send a single HTTP request to the EdgeCast API followed by ignoring the response back from the API. This created a much faster content editing experience for the users.

Note: The Expire module doesn't currently implement Domain module purging - the code class is empty. See issue #2293217 for details. We worked around this using the Cache Expiration Alias module.

The side effect of the Multi Curl development work was the speeding up of the single domain sites purge requests too!

The v2.0 EdgeCast module is available now for Drupal 7.

Find out more about the content delivery network from Edgecast.

Jun 02 2014
Jun 02

DCon-Amsterdam-logo

DCon-Amsterdam-logo

DrupalCon Austin 2014 is in full swing as of tomorrow,  my attendance is restricted to watching live feeds of the keynotes and the session recordings on Drupal Association’s Youtube channel … having not made it to the North American Con (again!)… thought I’d put the little down time between contracts to prepare for DrupalCon Amsterdam, on what I propose to share in two sessions freshly submitted.

Both in the business track;  one more a workshop than a traditional session… am quite excited at the prospect of having one if not both selected (fingers crossed). The first one I have proposed is a more indepth version of my ‘Practical Agile Product Development’ session recently delivered at Drupal Drupal Camp Yorkshire 2014 Agile Product Development

Drupal Camp Yorkshire 2014 Agile Product Development

Camp Yorkshire. Its 16 years of experience of delivering products, projects and transformation programs using various flavours of Agile, from James Martin’s RAD (Rapid Application Development) for getting products out of the door in their minimum viable form to giving the chaos structure using Dynamic systems development method (DSDM) to falling in love with the simplicity of SCRUM and then the combination of SCRUM and KANBAN: SCRUMBAN. From the beginning to date the challenge remains selecting which flavour of Agile is best suited for the engagement… and more challenging still occasions when the herd is convinced on not using Agile at all and its my job to swing the Jury in the opposite direction, this happens more so on the non-tech elements of a transformation program than the tech aspects of course.

Agile Digital Consultancies Vs the Big 4

Agile Digital Consultancies Vs the Big 4

The second session I have proposed is about getting agencies of all sizes in the community better tooled up to face off  Tier 1 & 2 consultancies and systems integrators who are increasingly and rapidly developing their Drupal capabilities given the size and scale of the opportunities in the Enterprise space. What started of as a niche platform has gone mainstream and with it has brought the big full service firms in to Drupalverse, which folks is a great thing for all involved in Drupal, FOSS and Enterprise!

Then there is the wider shift of agencies moving in to digital consulting since many of the Tier 1’s have historically lacked the depth agencies have built up over the years in the digital realm. So my second proposed session ‘Understanding your prospects, clients, stakeholders (Jury) and end users‘ is an in depth look at three models, my current favorites; Empathy maps to better understand the actors in your ecosystem, HotHousing  an exploration framework that mixes creative design thinking options with agile delivery outcomes, and Jobs-To-Be-Done framework (JTBD) a way to understand customer’s needs, motivations and behaviours. All three together are a powerful toolkit for any engagement be it tactics to approach a new prospect, running productive workshops with clients or ascertaining the ‘true’ needs of end users and facilitating them to articulate them and then co-designing options for fulfilling them.

Fingerscrossed I’ll get to share my knowledge and experiences on both Agile and Digital Consulting, however if there could be only one… I’d jump on the opportunity to tool up the community to better understand and engage with their prospects, clients, stakeholders (Jury) and end users.

Drupal Give back

Drupal Give back

For the curious this post is called Give back  for it is exactly that, back in 2012 in Munich I shared the challenges I was facing bringing peripheral communities into the fold with the global community, who in turn rallied to my aid and between Munich 2012 and Austin 2014 me and a few local hosts have kicked off four 1st ever Camps in 4 cities in two countries and been an inspiration for another two. Sharing what many of my peers in the consulting space prefer to keep to themselves as their magic models, I would like to believe sharing them with the community is my own personal give back, a huge thank you of sorts. Gondor returning the favour to Rohan if that’s your thing… or Lannisters paying a debt if you are so inclined!

Jun 01 2014
Jun 01

The community in the North… is quite hospitable and the Camp in the North was fantastic :)

:)


Drupal Camp Yorkshire 2014

Drupal Camp Yorkshire 2014

Back at Drupal Camp London Paul Driver invited me to Drupal Camp Yorkshire to deliver a session at the Camp. Drupal Camp Yorkshire 2014 was the 2nd Camp up in Leeds I am told, but from the experience I had for the short while I was there it could have been the 10th… it was  very well organised camp no doubt and next time round I will have to make sure I juggle my diary to be able to stay for the entire weekend.

Its been 6 or 7 years since I have been up to Leeds, driven past many a times but did not have an excuse to stop over, Drupal Camp is probably up there in the top 5 excuses to stop over or visit… but before I jump into the details I must mention another community who like myself had taken the Saturday off to take part in a very different but essential sort of activism.

2014-05-31 13.46.51

2014-05-31 13.46.51

On the train up to Leeds I met with a couple of ladies heading up from London, volunteers who were much like our own community giving up their Saturdays to give back.

Did’nt quite catch their names but they were activists heading up to Newark to give them folks from UKIP a hard time and to help the community there see UKIP  true ‘far right’  colours. I would like to thank folks like them who keep Britain grounded and heading in the right direction, giving geeks like me and others the ‘space’ to build, focus on and be part of other communities that rely on a certain kind of society to keep looking ahead and progressing in the right direction… probably not as eloquently put as I could.. but I am going to blame the beautiful sunny Sunday that it is right now!

Ok, back on topic, My session was on ‘Practical’ Agile product development and you can watch the video below to understand what I mean by that.

[embedded content] You can view/download the slides from Slideshare.com.

Lastly I must mention the venue, Electric Press at the Carriageworks Theatre in Leeds was by far the most picturesque of Drupal Camp venues I have have been to so far, over looking the Millenium square which given the weather was bursting with life and an open air concert set the scene up for a community event quite well.

Excellent job done by the organisers, a huge thank you to everyone who attended my session and apologies to a few friends I could not see or spend time with… for I dashed in and dashed out but will make it up to them at the next Camp or at the Con in Dam.

“Communication leads to community, that is, to understanding, intimacy and mutual valuing.”
Rollo May

Apr 17 2014
Apr 17

The background:

At the end of 2013 I started to think about where I currently am work-wise, and what I enjoy and want to do with myself now. My drupal-based startup Hello Pretty has been growing at a fantastic rate, and is also self sustaining enough now that I can step away without harming it. We've built it with an ideal of keeping things technically as simple as possible and rather focusing our money & energy on marketing.

In my job at NowPublic I managed the dev team (rather than doing any programming myself. After 20 years of it I've started to get a bit bored). I loved that job and decided that I'd like to get back into that.

In January I began the process of looking for jobs. This would most likely have meant leaving our beautiful home in Cape Town and moving to where the work was. So it was no small decision for Sam and I.

At the end of February two very cool companies for positions I hadn't applied to contacted me two days apart, both through word-of-mouth references from people I've worked with previously. After a handful of rejections in the process already, I was ecstatic. One was in one of my favourite cities in the world, Vancouver :), and the other - Acquia - I've followed since day one of it's existence and have several friends and former colleagues who work there.

After chatting to the company in Vancouver a couple of times, they were quite keen and waiting to hear back on where I stood.

As I write this I keep thinking back to one of my favourite quotes and wondering why I didn't heed this advice sooner. It refers to a person's character or nature, and that how they handle anything small or 'unimportant' most likely reflects how they handle everything big or important.

How you do anything is how you do everything

My Acquia Story

Note: I don't blame any individual for my experience, but rather a culture within the company. Any names of the people who I spoke to have been changed.

Week 1

Matt from Acquia and I chatted on Skype video for about an hour. He was the person most involved in hiring me, and making a final call. We discussed my skills and qualifications, my salary expectations, and the fact that I had another company waiting for a response from me. He was keen to chat more and would try to keep the process quick so that I didn't have to keep the Vancouver company waiting long. He asked whether I'd be ok to have interviews over the next week. I agreed and said I'd explain the situation to the other company. After those were done there'd still be the meetings with the CEO and CTO of Acquia. He couldn't promise that it would be easy to schedule with them, so there could be additional delays.

This was on Wednesday morning Boston-time.

Week 2

By the following Monday at mid day, 6 days later, I still hadn't heard from them and assumed that he'd changed his mind. Not a big deal. But then, a recruiter from Acquia finally emailed me to schedule some interviews. Yay!

I sent back my schedule and... nothing. I understood from friends that Acquia usually want a few interviews, and the week was quickly coming to an end.

I followed up with the recruiter explaining that there was some urgency and that I didn't want to keep the Vancouver company waiting - I'd already put them off for a full week at this point. In the interest of expediting the process I offered to rearrange my own schedule or meet at short notice. I also asked for a sense of Acquia's timeline.

The recruiter promptly responded by setting up 4 interviews over the next two days. Three of them after 8pm my time, and one of them scheduled from 11:30pm to 12:30am. Ok, I figured, people are busy, and if this was going to get things done sooner, then great. Besides, this would give me bragging rights for having had a job interview at midnight.

After those 4 interviews I was asked to review the product I'd be working with to provide feedback, suggestions, etc. which I did over the weekend. I spent a few hours figuring it out, and working on my review. Obviously I wanted to impress, and the feedback I got from them (on my feedback) was very positive. I was actually really impressed with what I saw. Acquia is doing a lot of very cool stuff that I'd had no idea about.

Week 3

I had now kept the company in Vancouver waiting considerably longer than I'd told them I would. I hate keeping people waiting, in any context, and if I tell someone I'm going to do anything by a certain date or time it's important to me to stick to it. That goes for work and personal commitments.

On Monday (day 13) I'd again had no word. I followed up on Tuesday. "Interviews would be scheduled shortly". Matt asked if it would be ok to do this on very short notice and how late I could meet. Keen to wrap things up, I agreed to meet at any time.

After those next two interviews, radio silence. Matt said he'd "touch base to follow up with next steps". And then more radio silence. Two days later he got back to me to say he was having the recruiter set up more interviews. And sure enough, on Friday that week the recruiter mailed me to arrange a few more interviews.

This was when I started feeling demoralized. Why had they only scheduled two interviews in the entire week when I'd made my schedule completely open to them? Why did they continue to schedule interviews after 8pm for me (that's after 2pm Boston-time) if they were only going to schedule two or three in a week? I knew there was one other candidate, I had no idea where I stood, and it was never communicated to me how many more interviews there might be. I'd made my schedule very flexible for Acquia, and I'd pushed back my other job to the point where I was being straight-up disrespectful to them.

I decided to get back to the guys in Vancouver and figure out next-steps with them.

I've interviewed for jobs in the past, and I've interviewed people for jobs. I'm quite familiar with the "normal" process from both ends. Never had I been involved in, or even heard of, had such a long, stretched out and uncomfortably bureaucratic process. I hardly expected it from a company who claims to want to move quickly, and one who I hadn't applied to, but had actually approached me in the first instance. This is a company whose CEO subscribes to a philosophy of Ready, Fire, Aim. I'm of the opinion that, if you can't make a decision after 4 interviews... DO NOT HIRE. It's a sign that something's wrong, maybe just a gut feeling, but something worth listening to. I'd had 7 interviews by now, with 3 more scheduled for the following week.

I began seriously questioning whether I could work for a company with such bureaucratic, non-transparent and slow processes. Was this how things operate internally too? It was hard for me to believe that they could have a hiring process like this and still function acceptably within the rest of the company. But, I have a lot of friends who work for Acquia and they all seem to really enjoy working there.

The recruiter asked for times early the following week, so I again opened up my entire schedule including late night interviews. For anyone who's never done a late night interview, I'll tell you right now that they're extremely challenging. After a full day of work (I've been putting in 10 to 12 hour days), after hanging out, eating dinner, it's time to snap out of it and get ready. Get out of your PJs, put on a nice shirt, and get focussed. It's always important to be on top of your game in any interview. This means being wide awake and involves adrenaline.

No pants interview

The interviews themselves are always intense. Almost always enjoyable for me too, since I love chatting with interesting people (and everyone I spoke to at Acquia was interesting). Regardless, if my interview ends at 11pm, I won't be getting to sleep before 2am at the absolute earliest. This means a slow day to follow it up. Of course I had no idea that this would be the case when I first started agreeing to these, and I also thought I'd be looking at 7 days of it, not at least 3 weeks of it (at the end of which I still didn't have any clue as to when it would all end).

Week 4

My meetings for the week were set up, the final one being at 9pm on Friday. The first interview of the week was with Matt again. I'd hoped to get a chance to get clarity on the process, but no dice. I was caught a bit off guard as he grilled me again on things we'd already discussed in our first and second interviews, and that were brought up by the developers I spoke to in week 3. I had another interview immediately after that which was probably my favourite of the bunch but at the end of it all I was left feeling very disheartened with no idea what was going on.

While I was moving forward with the Vancouver company, all of this was still upsetting. I was under the impression when they contacted me that this would take a week, and it had now been dragged out over 4 (with no end in sight). Had I known up front that they required 10-12 interviews I'd have turned them down immediately and saved everybody a lot of time.

Through all this, and despite feeling the way I did, everyone at Acquia seemed very smart and like people I'd have really enjoyed working with. I felt I had a great vibe with Matt and even if this didn't work out, every one of the team would have been a person I'd have enjoyed having a beer with next time I was in Boston.

This is why the response I received the following Monday was so shocking.

Week 5

REJECTED!

Hi Scott,

Thank you for taking the time to interview with us for our Director, Acquia {DIVISION HIDDEN} opening. Our team has had a chance to discuss your qualifications, and unfortunately, I have decided to pursue other candidates who appear to match (skills and experience) our requirements more closely at this time.

Should something change on our side (or I get another job opening that matches your background better), I will not hesitate to contact you.

Thank you again for your interest in an employment opportunity with Acquia, Inc., and I wish you the best of luck in your current job search.

Thanks,
[Recruiter's Name]

I was in shocked disbelief. Not because I was turned down for the job though: I had in fact received this identical message two months earlier when I applied for an unrelated position at Acquia. They'd looked at my resume and turned me away without any interviews. And now, after:

  • 3 interviews with Matt,
  • a lot of back and forth emails discussing the company and position,
  • a couple of hours spent reviewing and reporting on the project I'd be managing,
  • 4 weeks, and
  • 10 interviews, with
  • 8 people...

... I got a template rejection? And not even from Matt himself, but from the recruiter he delegated it to.

It took a full day of thinking to figure out whether I was upset because I didn't get the job, or because I'd been treated in such a disrespectful way. I'd believed that I'd had a great vibe with Matt, and that the task of sending me my template rejection had been delegated to a recruiter was insulting.

I'll be honest, I was so furious that first day that I considered working for one of their competitors with the sole purpose of taking them down. The next day after I'd got my head back on straight I realized that that would be a strange focus to put on my life for at least the next decade. I spoke to a friend at Acquia and asked if he thought this (the process, not my malicious aspirations) was normal. He couldn't believe my story, and promptly spoke to Matt about what had happened.

I don't think Matt realized I'd be getting a template response, and after learning so from my friend he quickly sent me an apology mail for it. While his mail explicitly said "Either way, no excuses", it was still surprisingly full of excuses (such as being too swamped).

Now, for all I know Matt wanted to send me a long detailed response or call me to explain everything but really was too swamped to. However, considering that he knew I was under pressure with another company and availed myself for what turned out to be a 10-interview gauntlet, a quick 2-liner explaining that I was rejected and setting up a call would have been appreciated.

The Moral

I feel that my quote here applies firmly. When you start seeing red flags like a company taking advantage of a person's offer of flexibility (or anything else), unnecessary bureaucracy, and a lack of transparency, it's probably time to call it a day and cut off communication with them (unless you work well in that environment). After the way I felt during the whole process, should I really have been surprised with the way my rejection was handled?

Nobody, whether applying to a position as a CEO or a janitor, should be treated with such discourtesy by the company interviewing them.

For Acquia:

Despite dealing more with Matt than anyone else, I certainly don't put the full blame on him. I believe that what happened here is the result of culture and attitude within Acquia.

You have a CEO who contradictorily states that he won't hire anyone with a Ready Aim Fire mentality. Acquia's hiring process is exactly that. Dries (the CTO) says he wants Acquia to do well and good such as acting as a driver to build up and support the Drupal community, yet at the same time the company is treating job candidates (many from within that same community) extraordinarily disrespectfully.

To those at Acquia who are in a position where they can make positive change: it's time you look at your processes and question them. Another friend at Acquia told me that the HR and hiring process is something you're proud of. If you happen to read this post and you're proud of the actions taken, well, I appreciate the rejection.

I'm almost certainly not an isolated case. Much of the Acquia team is made up of loyal members of the Drupal community, and I'd guess that a large percentage of the applicants are community members too (myself included).

Jan 27 2014
Jan 27
teaser image for blog post

What's the point in using an IDE, especially a paid one, for PHP development when there are so many simpler, free tools?

In November 2013 I was lucky enough to be offered the chance to present a session at DrupalCamp NW on why it's time for Drupal developers to be using a proper IDE. The session used JetBrains PhpStorm as an example, but presented the case including other popular IDEs like Eclipse and NetBeans as well.

Drupal is getting more and more complicated, and, as developers, we should feel obliged to create code that looks good, does what it says on the tin, and works every time. An IDE provides modern functionality like syntax highlighting, step debugging, and other niceties, such as the ability to look up function documentation then and there in the IDE without needing to browse to a website. It also provides a whole bunch of error checking, like making sure you return the correct values from functions, or using static methods correctly, with zero effort required.

Coding standards is a big thing. Nobody's required to do it at the moment, but in the past, Drupal's contrib has filled up with poorly formatted code, or just code that is difficult to read or written in an alien style. In the past, we had to write our code, then run a command to review it before making a commit, which was a pain. With modern IDEs, we can be shown coding standards errors as we type them, so not only can we make fewer mistakes when we commit, but we learn instantly what kind of formatting to avoid and what kind works well.

As we move towards a more object-oriented approach in Drupal 8, away from procedural code, hopefully we will migrate to good object-oriented patterns. This often means jumping around in code more and more, since we will be writing one object per file, and sometimes method implementations are inherited from higher up in the hierarchy. An IDE makes the task a lot simpler, and you're able to see quickly and easily where an object gets its stuff from, and whether you have overridden or implemented methods correctly.

Although a PhpStorm licence comes at a yearly cost, I feel that the time saved more than makes up for the fee. Many people in the Drupal community are Apple users (or fans) and think nothing of laying down over £800 for a new Macbook! A PC would do, but many feel that the convenience and experience of using a Mac is a better way, and the same applies to PhpStorm!

In short, as a Drupal community, we already have a wealth of contributed modules that do a whole host of useful things, but now we should be focusing more on code quality and documentation, to involve more people more easily, and make sure things like updating modules and providing extra functionality are a breeze, not a chore riddled with semantic or conceptual problems. Nobody's forcing you to use an IDE, but if it'll help you write better code and make a more positive contribution to Drupal, at no (or little) extra cost, maybe it's time to make the switch.

Here is the video of the session:
[embedded content]

And the presentation slides:
Phpstorm & Drupal presentation from DrupalCamp NW 2013

Dec 05 2013
Dec 05

November was huge for the Open Source community in Middle Earth, Those who attended Drupal Camp Karachi on 2nd November and Dubai on the 30th of November 2013 made history. I shall get to Karachi later, this post is about Dubai Camp, challenges of organising it and the outcome of the journey that started in June 2013.

BaY96-QIQAAQ_I3

BaY96-QIQAAQ_I3

As organisers our focus was both quality and quantity of course; share best practises, tools and knowledge with as many as possible! though we did not get the quantity, 80+ were invited 55 were expected and the campers peaked at lunch with a turn out of 45… and for the last session and closing we had 20.

Organising Dubai camp was a challenge for the organising committee… though committee sounds grand! there was me, Ahmed Koshok and Massoud Al-Shareef, with two regionals on board you might expect things to be easier but with no boots on the ground mobilisation of the community, securing the venue, putting the logistics in place was always going to be a challenge! but planning for it made it that tad bit easier.

DCAE_Email_Volume_2013

DCAE_Email_Volume_2013

At first there was just me (and making very slow progress), then Ahmed came on board and both of us dragged the vision of Dubai camp a fair distance but nowhere close to the starting line… then in Massoud we found a regional champion and a reliable network on the ground to go through the red tape… that was Hani Hejazi; and securing the venue was Hani’s feat. From start to finish organising Dubai camp took 6 months!

DCAE_pic_4_2013

DCAE_pic_4_2013

DC Dubai had a strong contingent of local/regional Drupal rockstars in attendance and that was the magic sauce in Dubai camp, from a total of 16 speakers/trainers we had 9 local/regional speakers/trainers and that was a coup for any first camp I have attended or been a part of in Middle Earth.

At Dubai camp there were many firsts! the faculty was not just curious but participatory and super supportive, Professor Jassim Jirjees the program director for MLIS was in attendance and his staff ensured everything ran like clockwork!

To top it all Professor Muthanna G. Abdul Razzaq the president of AUE announced a full scholarship for anyone applying from within the Drupal community… we shall get the details for application, prerequisites etc and post them on our Facebook page.

A super supportive and involved institution, local rockstars in attendance, informed and engaging speakers, an awesome regional community to network with and a tasty lunch… made it epic.

From Ahmed Koshok, Massoud Al-Shareef and me a huge thank you shoutout to:

And I would not have been able to co-organise Dubai Camp had it not been for Ahmed Koshok, Massoud Al-Shareef, Jihan Al-Shareef, Hani Hijazi  and Marwa Ezzat – we made an awesome team folks! thank you and lets get going for the next one!

For session slides please follow the DrupalCamp Dubai twitter account and we shall be releasing the slides as and when we receive them from the speakers, a few are already up on Twitter.

Looking forward to hearing about meet-ups in KSA, UAE, Bahrain, Egypt, Jordan and beyond!

Pages

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web