Run prettier on all *.md files
``` prettier '{app,source}/**/**.md' --write ```
This commit is contained in:
parent
a3ceeaf0f3
commit
85a10c545b
|
@ -3,4 +3,5 @@ title: Page Not Found
|
|||
permalink: /404.html
|
||||
use: [posts]
|
||||
---
|
||||
|
||||
Please [contact me](/contact/) and let me know.
|
||||
|
|
|
@ -2,25 +2,38 @@
|
|||
layout: front
|
||||
title: About Me
|
||||
meta:
|
||||
og:
|
||||
title: 'Oliver Davies - Full Stack Developer, System Administrator, PHP and Drupal specialist'
|
||||
description: 'The personal website and blog of Oliver Davies, a Full Stack Developer and System Administrator from Wales, UK.'
|
||||
type: website
|
||||
og:
|
||||
title:
|
||||
'Oliver Davies - Full Stack Developer, System Administrator, PHP and
|
||||
Drupal specialist'
|
||||
description:
|
||||
'The personal website and blog of Oliver Davies, a Full Stack Developer
|
||||
and System Administrator from Wales, UK.'
|
||||
type: website
|
||||
permalink: /
|
||||
---
|
||||
|
||||
<div class="mb-4 w-32"><img src="/images/me-precedent.jpg" alt="Picture of Oliver" class="rounded-full border border-gray"/></div>
|
||||
|
||||
Hi, I'm Oliver Davies (aka [opdavies](https://www.google.com/#q=opdavies)).
|
||||
I’m a {{ site.work.role }} at [{{site.companies[site.work.company].name}}]({{site.companies[site.work.company].url}}) and a part-time freelance Web Developer, based in Wales, UK.
|
||||
Hi, I'm Oliver Davies (aka [opdavies](https://www.google.com/#q=opdavies)). I’m
|
||||
a {{ site.work.role }} at
|
||||
[{{site.companies[site.work.company].name}}]({{site.companies[site.work.company].url}})
|
||||
and a part-time freelance Web Developer, based in Wales, UK.
|
||||
|
||||
I’ve been a Developer since 2007 and specialise in using Drupal, Symfony and Vue.js, though I also use other technologies including Laravel and Sculpin.
|
||||
I use Ansible for server provisioning and application deployments.
|
||||
I’ve been a Developer since 2007 and specialise in using Drupal, Symfony and
|
||||
Vue.js, though I also use other technologies including Laravel and Sculpin. I
|
||||
use Ansible for server provisioning and application deployments.
|
||||
|
||||
I’m an [Acquia certified](https://certification.acquia.com/user/1647756) Drupal 8 Grand Master, and Webmaster and Documentation Maintainer on [Drupal.org](https://www.drupal.org).
|
||||
I was previously a Developer for the [{{site.companies.drupal_association.name}}]({{site.companies.drupal_association.url}}).
|
||||
I’m an [Acquia certified](https://certification.acquia.com/user/1647756) Drupal
|
||||
8 Grand Master, and Webmaster and Documentation Maintainer on
|
||||
[Drupal.org](https://www.drupal.org). I was previously a Developer for the
|
||||
[{{site.companies.drupal_association.name}}]({{site.companies.drupal_association.url}}).
|
||||
|
||||
I regularly [give talks](/talks) at user groups and conferences,
|
||||
and am an organiser of the [{{site.events.php_south_wales.name}}]({{site.events.php_south_wales.url}}) user group.
|
||||
I regularly [give talks](/talks) at user groups and conferences, and am an
|
||||
organiser of the
|
||||
[{{site.events.php_south_wales.name}}]({{site.events.php_south_wales.url}}) user
|
||||
group.
|
||||
|
||||
I enjoy contributing to open source, and maintain a variety of different projects.
|
||||
You can see these on my [Drupal.org]({{site.drupalorg.url}}) and [GitHub]({{site.github.url}}) accounts.
|
||||
I enjoy contributing to open source, and maintain a variety of different
|
||||
projects. You can see these on my [Drupal.org]({{site.drupalorg.url}}) and
|
||||
[GitHub]({{site.github.url}}) accounts.
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
title: Accessibility
|
||||
use: [posts]
|
||||
---
|
||||
|
||||
# Accessibility
|
||||
|
||||
I have made as much effort as possible to make this website accessible to all users.
|
||||
I have made as much effort as possible to make this website accessible to all
|
||||
users.
|
||||
|
||||
If you have any suggestions to improve the site, please [contact me](/contact/).
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
---
|
||||
title: Company Information
|
||||
meta:
|
||||
description: 'Company information for Oliver Davies Ltd.'
|
||||
description: 'Company information for Oliver Davies Ltd.'
|
||||
use: [posts]
|
||||
---
|
||||
|
||||
# Company Information
|
||||
|
||||
Company name
|
||||
: Oliver Davies Ltd (previously Oliver Davies Web Development Ltd)
|
||||
Company name : Oliver Davies Ltd (previously Oliver Davies Web Development Ltd)
|
||||
|
||||
Registered address
|
||||
: 106 Rowan Way, Malpas, Newport, NP20 6JN
|
||||
Registered address : 106 Rowan Way, Malpas, Newport, NP20 6JN
|
||||
|
||||
Company number
|
||||
: 8017706
|
||||
Company number : 8017706
|
||||
|
|
|
@ -3,4 +3,6 @@ title: Thanks!
|
|||
permalink: contact/thanks/
|
||||
use: [posts]
|
||||
---
|
||||
Your email has been sent. You should receive a response within the next working day.
|
||||
|
||||
Your email has been sent. You should receive a response within the next working
|
||||
day.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
---
|
||||
title: Developing this Website (WIP)
|
||||
---
|
||||
This site is built with [Sculpin][], a static site generator written in PHP, that generates a static HTML website from Markdown files and Twig templates. You can see the [source code on GitHub].
|
||||
|
||||
## Extending Sculpin
|
||||
This site is built with [Sculpin][], a static site generator written in PHP,
|
||||
that generates a static HTML website from Markdown files and Twig templates. You
|
||||
can see the [source code on GitHub].
|
||||
|
||||
## Extending Sculpin
|
||||
|
||||
- Custom Twig extensions
|
||||
- https://github.com/opdavies/sculpin-twig-markdown-bundle
|
||||
|
@ -12,11 +15,14 @@ This site is built with [Sculpin][], a static site generator written in PHP, tha
|
|||
|
||||
## Front End
|
||||
|
||||
On the front-end, I have used [PostCSS][] rather than Sass or Less, and [Tailwind CSS] for all of the styling, and some [Vue.js][] for the navbar and toggling the navigation menu on mobile. These are compiled with [Webpack Encore][] - a wrapper around Webpack, provided by Symfony.
|
||||
On the front-end, I have used [PostCSS][] rather than Sass or Less, and
|
||||
[Tailwind CSS] for all of the styling, and some [Vue.js][] for the navbar and
|
||||
toggling the navigation menu on mobile. These are compiled with [Webpack
|
||||
Encore][] - a wrapper around Webpack, provided by Symfony.
|
||||
|
||||
[PostCSS]: https://postcss.org
|
||||
[Sculpin]: https://sculpin.io
|
||||
[source code on GitHub]: https://github.com/opdavies/oliverdavies.uk
|
||||
[Tailwind CSS]: https://tailwindcss.com
|
||||
[Vue.js]: https://vuejs.org
|
||||
[Webpack Encore]: https://github.com/symfony/webpack-encore
|
||||
[postcss]: https://postcss.org
|
||||
[sculpin]: https://sculpin.io
|
||||
[source code on github]: https://github.com/opdavies/oliverdavies.uk
|
||||
[tailwind css]: https://tailwindcss.com
|
||||
[vue.js]: https://vuejs.org
|
||||
[webpack encore]: https://github.com/symfony/webpack-encore
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
---
|
||||
---
|
||||
|
||||
<div class="markup" markdown="1">
|
||||
# Speaker Info
|
||||
|
||||
## Bio
|
||||
|
||||
[Oliver Davies][website] ([@opdavies][twitter]) has been building websites since 2007, and speaking at meetups and conferences since 2012. He is a Full Stack Developer and an Acquia certified Drupal Grand Master, who also has
|
||||
experience developing with Symfony, Laravel, Sculpin and Vue.js, as well as with DevOps and systems administration.
|
||||
[Oliver Davies][website] ([@opdavies][twitter]) has been building websites since
|
||||
2007, and speaking at meetups and conferences since 2012. He is a Full Stack
|
||||
Developer and an Acquia certified Drupal Grand Master, who also has experience
|
||||
developing with Symfony, Laravel, Sculpin and Vue.js, as well as with DevOps and
|
||||
systems administration.
|
||||
|
||||
He is a {{ site.work.role }} at [{{ site.companies[site.work.company].name }}][work], a Drupal core contributor and mentor, and an open source and contribution advocate.
|
||||
He is a {{ site.work.role }} at
|
||||
[{{ site.companies[site.work.company].name }}][work], a Drupal core contributor
|
||||
and mentor, and an open source and contribution advocate.
|
||||
|
||||
He regularly blogs and gives talks on various topics, maintains and contributes to various open source projects, and co-organises the PHP South Wales user group.
|
||||
He regularly blogs and gives talks on various topics, maintains and contributes
|
||||
to various open source projects, and co-organises the PHP South Wales user
|
||||
group.
|
||||
|
||||
[twitter]: {{site.twitter.url}}
|
||||
[website]: {{site.url}}
|
||||
|
||||
[work]: {{site.companies[site.work.company].url}}
|
||||
|
||||
## Photos
|
||||
|
@ -35,4 +44,4 @@ He regularly blogs and gives talks on various topics, maintains and contributes
|
|||
- PHP South Coast 2016
|
||||
- PHP UK Conference 2018
|
||||
- WordCamp Bristol 2019
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
---
|
||||
title: Live Streaming
|
||||
---
|
||||
I like try and do some live coding when I can, whether I’m working on a side project, my own website or some open source code. You can find my [stream link on YouTube][0], or view some previous streams below:
|
||||
|
||||
I like try and do some live coding when I can, whether I’m working on a side
|
||||
project, my own website or some open source code. You can find my [stream link
|
||||
on YouTube][0], or view some previous streams below:
|
||||
|
||||
## Stream Playlists
|
||||
|
||||
- [Miscellaneous coding live streams][1]
|
||||
{# - [Building the PHP South Wales website][2] #}
|
||||
{# - [Using PHP to generate Gmail Filter XML with the Gmail Filter Builder][3] #}
|
||||
- [Miscellaneous coding live streams][1] {# - [Building the PHP South Wales
|
||||
website][2] #} {# - [Using PHP to generate Gmail Filter XML with the Gmail
|
||||
Filter Builder][3] #}
|
||||
|
||||
[0]: {{site.youtube.stream.url}}
|
||||
[1]: https://www.youtube.com/playlist?list=PLHn41Ay7w7kcWbjrYaiqXlfrqi_teTJE8
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
title: Development Terms
|
||||
use: [posts]
|
||||
---
|
||||
|
||||
# Development Terms
|
||||
|
||||
TODO
|
||||
|
|
|
@ -3,11 +3,14 @@ title: 'Test Driven Drupal: The Book'
|
|||
mailchimp_url: 'https://oliverdavi.us18.list-manage.com/subscribe/post?u=b4ac8dd177796d37b93f9c285&id=033c84e0d5'
|
||||
contact_email: 'oliver@testdrivendrupal.com'
|
||||
---
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="markup spaced-y-4 mb-6" markdown="1">
|
||||
Having [given talks][1] and workshops, been a guest on podcasts and [written articles][0] about automated testing in Drupal, I’m currently in the planning phase of a book and potentially some accompanying screencasts about it, focussing on Drupal 8.
|
||||
|
||||
I’m still thinking about what use-cases to cover and examples to include, but here are some of the things I’m considering:
|
||||
I’m still thinking about what use-cases to cover and examples to include, but
|
||||
here are some of the things I’m considering:
|
||||
|
||||
- What things to test, and what not to test
|
||||
- The different types of available tests, and when to use each
|
||||
|
@ -30,19 +33,23 @@ I’m still thinking about what use-cases to cover and examples to include, but
|
|||
- Testing queuing items and processing queues
|
||||
- Testing sending emails
|
||||
- Testing custom Twig filters and functions
|
||||
<!-- - Testing data migrations -->
|
||||
<!-- - Building and testing APIs using RESTful web services module -->
|
||||
<!-- - Testing data migrations -->
|
||||
<!-- - Building and testing APIs using RESTful web services module -->
|
||||
- Running tests as part of your continuous integration pipeline
|
||||
|
||||
I’ll most likely be publishing it via Leanpub, and will be sending free chapters, early-bird discounts and links to screencasts and blog posts as I write the book to subscribers of the mailing list.
|
||||
I’ll most likely be publishing it via Leanpub, and will be sending free
|
||||
chapters, early-bird discounts and links to screencasts and blog posts as I
|
||||
write the book to subscribers of the mailing list.
|
||||
|
||||
If you have questions or would like to suggest something for me to include in the book, please <a href="mailto:{{ page.contact_email }}">contact me</a>.
|
||||
If you have questions or would like to suggest something for me to include in
|
||||
the book, please <a href="mailto:{{ page.contact_email }}">contact me</a>.
|
||||
|
||||
**Enter your email address to subscribe to the Test Driven Drupal mailing list
|
||||
and be notified of any updates.**
|
||||
|
||||
**Enter your email address to subscribe to the Test Driven Drupal mailing list and be notified of any updates.**
|
||||
</div>
|
||||
|
||||
{% include 'pages/book/signup-form' %}
|
||||
{% endblock %}
|
||||
{% include 'pages/book/signup-form' %} {% endblock %}
|
||||
|
||||
[0]: /articles/tags/testing
|
||||
[1]: /talks/tdd-test-driven-drupal
|
||||
|
|
|
@ -8,41 +8,77 @@ tags:
|
|||
- personal
|
||||
tweets: true
|
||||
---
|
||||
A lot happened in 2014. Here are some of the main things that I'd like to highlight.
|
||||
|
||||
A lot happened in 2014. Here are some of the main things that I'd like to
|
||||
highlight.
|
||||
|
||||
## Joined the Drupal Association
|
||||
|
||||
This was the main thing for me this year, in May I left [Precedent](http://precedent.com) and joined the [Drupal Association](https://assoc.drupal.org). I work on the Engineering team, focused mainly on [Drupal.org](https://www.drupal.org) but I've also done some theming work on the DrupalCon [Amsterdam](http://amsterdam2014.drupal.org) and [Latin America](http://latinamerica2015.drupal.org) websites, and some pre-launch work on [Drupal Jobs](https://jobs.drupal.org).
|
||||
This was the main thing for me this year, in May I left
|
||||
[Precedent](http://precedent.com) and joined the
|
||||
[Drupal Association](https://assoc.drupal.org). I work on the Engineering team,
|
||||
focused mainly on [Drupal.org](https://www.drupal.org) but I've also done some
|
||||
theming work on the DrupalCon [Amsterdam](http://amsterdam2014.drupal.org) and
|
||||
[Latin America](http://latinamerica2015.drupal.org) websites, and some
|
||||
pre-launch work on [Drupal Jobs](https://jobs.drupal.org).
|
||||
|
||||
Some of the tasks that I've worked on so far are:
|
||||
|
||||
* Fixing remaining issues from the Drupal.org Drupal 7 upgrade.
|
||||
* Improving pages for [Supporting Partners](https://www.drupal.org/supporters/partners), [Technology Supporters](https://www.drupal.org/supporters/technology) and [Hosting Partners](https://www.drupal.org/supporters/hosting). These previously were manually updated pages using HTML tables, which are now dynamic pages built with [Views](https://www.drupal.org/project/views) using organisation nodes.
|
||||
* Configuring human-readable paths for user profiles using [Pathauto](https://www.drupal.org/project/pathauto). Only a small change, but made a big difference to end-users.
|
||||
* Migration of user data from profile values to fields, and various user profile improvements. This was great because now we can do things like reference mentors by their username and display their picture on your profile, as well as show lists of peope listing a user as their mentor. This, I think, adds a more personal element to Drupal.org because we can see the actual people and not just a list of names on a page.
|
||||
- Fixing remaining issues from the Drupal.org Drupal 7 upgrade.
|
||||
- Improving pages for
|
||||
[Supporting Partners](https://www.drupal.org/supporters/partners),
|
||||
[Technology Supporters](https://www.drupal.org/supporters/technology) and
|
||||
[Hosting Partners](https://www.drupal.org/supporters/hosting). These
|
||||
previously were manually updated pages using HTML tables, which are now
|
||||
dynamic pages built with [Views](https://www.drupal.org/project/views) using
|
||||
organisation nodes.
|
||||
- Configuring human-readable paths for user profiles using
|
||||
[Pathauto](https://www.drupal.org/project/pathauto). Only a small change, but
|
||||
made a big difference to end-users.
|
||||
- Migration of user data from profile values to fields, and various user profile
|
||||
improvements. This was great because now we can do things like reference
|
||||
mentors by their username and display their picture on your profile, as well
|
||||
as show lists of peope listing a user as their mentor. This, I think, adds a
|
||||
more personal element to Drupal.org because we can see the actual people and
|
||||
not just a list of names on a page.
|
||||
|
||||
I've started keeping a list of tasks that I've been involved with on my [Work](/work/) page, and will be adding more things as I work on them.
|
||||
I've started keeping a list of tasks that I've been involved with on my
|
||||
[Work](/work/) page, and will be adding more things as I work on them.
|
||||
|
||||
### Portland
|
||||
|
||||
I was able to travel to Portland, Oregon twice last year to meet with the rest of the Association staff. Both times I met new people and it was great to spend some work and social time with everyone, and it was great to have everyone together as a team.
|
||||
I was able to travel to Portland, Oregon twice last year to meet with the rest
|
||||
of the Association staff. Both times I met new people and it was great to spend
|
||||
some work and social time with everyone, and it was great to have everyone
|
||||
together as a team.
|
||||
|
||||
## My First DrupalCamp
|
||||
|
||||
In February, I attended [DrupalCamp London](http://2014.drupalcamplondon.co.uk). This was my first time attending a Camp, and I managed to attend some great sessions as well as meet people who I'd never previously met in person. I was also a volunteer and speaker, where I talked about [Git Flow](/blog/what-git-flow/) - a workflow for managing your Git projects.
|
||||
In February, I attended [DrupalCamp London](http://2014.drupalcamplondon.co.uk).
|
||||
This was my first time attending a Camp, and I managed to attend some great
|
||||
sessions as well as meet people who I'd never previously met in person. I was
|
||||
also a volunteer and speaker, where I talked about
|
||||
[Git Flow](/blog/what-git-flow/) - a workflow for managing your Git projects.
|
||||
|
||||
{% include 'tweet' with {
|
||||
content: '<p>Great presentation by <a href="https://twitter.com/opdavies">@opdavies</a> on git flow at <a href="https://twitter.com/search?q=%23dclondon&src=hash">#dclondon</a> very well prepared and presented. <a href="http://t.co/tDINp2Nsbn">pic.twitter.com/tDINp2Nsbn</a></p>— Greg Franklin (@gfranklin) <a href="https://twitter.com/gfranklin/statuses/440104311276969984">March 2, 2014</a>'
|
||||
} %}
|
||||
|
||||
I was also able to do a little bit of sprinting whilst I was there, reviewing other people's modules and patches.
|
||||
I was also able to do a little bit of sprinting whilst I was there, reviewing
|
||||
other people's modules and patches.
|
||||
|
||||
Attending this and [DrupalCon Prague](https://prague2013.drupal.org) in 2013 have really opened my eyes to the face-to-face side of the Drupal community, and I plan on attending a lot more Camps and Cons in the future.
|
||||
Attending this and [DrupalCon Prague](https://prague2013.drupal.org) in 2013
|
||||
have really opened my eyes to the face-to-face side of the Drupal community, and
|
||||
I plan on attending a lot more Camps and Cons in the future.
|
||||
|
||||
## DrupalCon Amsterdam
|
||||
|
||||
I was also able to travel to Holland and attend [DrupalCon Amsterdam](https://amsterdam2014.drupal.org) along with other members of Association staff.
|
||||
I was also able to travel to Holland and attend
|
||||
[DrupalCon Amsterdam](https://amsterdam2014.drupal.org) along with other members
|
||||
of Association staff.
|
||||
|
||||
## DrupalCamp Bristol
|
||||
|
||||
In October, we started planning for [DrupalCamp Bristol](http://www.drupalcampbristol.co.uk). I'm one of the founding Committee members,
|
||||
In October, we started planning for
|
||||
[DrupalCamp Bristol](http://www.drupalcampbristol.co.uk). I'm one of the
|
||||
founding Committee members,
|
||||
|
|
|
@ -1,14 +1,30 @@
|
|||
---
|
||||
title: Accessible Bristol site launched
|
||||
date: 2012-11-15
|
||||
excerpt: I'm happy to report that the Accessible Bristol was launched this week, on Drupal 7.
|
||||
excerpt:
|
||||
I'm happy to report that the Accessible Bristol was launched this week, on
|
||||
Drupal 7.
|
||||
tags:
|
||||
- accessibility
|
||||
- accessible-bristol
|
||||
- nomensa
|
||||
---
|
||||
I'm happy to announce that the [Accessible Bristol](http://www.accessiblebristol.org.uk) website was launched this week, on Drupal 7. The site has been developed over the past few months, and uses the [User Relationships](http://drupal.org/project/user_relationships) and [Privatemsg](http://drupal.org/project/privatemsg) modules to provide a community-based platform where people with an interest in accessibility can register and network with each other.
|
||||
|
||||
The site has been developed over the past few months, and uses the [User Relationships](http://drupal.org/project/user_relationships) and [Privatemsg](http://drupal.org/project/privatemsg) modules to provide a community-based platform where people with an interest in accessibility can register and network with each other.
|
||||
I'm happy to announce that the
|
||||
[Accessible Bristol](http://www.accessiblebristol.org.uk) website was launched
|
||||
this week, on Drupal 7. The site has been developed over the past few months,
|
||||
and uses the [User Relationships](http://drupal.org/project/user_relationships)
|
||||
and [Privatemsg](http://drupal.org/project/privatemsg) modules to provide a
|
||||
community-based platform where people with an interest in accessibility can
|
||||
register and network with each other.
|
||||
|
||||
The group is hosting a launch event on the 28th November at the Council House, College Green, Bristol. Interested? More information is available at <http://www.accessiblebristol.org.uk/events/accessible-bristol-launch> or go to <http://buytickets.at/accessiblebristol/6434> to register.
|
||||
The site has been developed over the past few months, and uses the
|
||||
[User Relationships](http://drupal.org/project/user_relationships) and
|
||||
[Privatemsg](http://drupal.org/project/privatemsg) modules to provide a
|
||||
community-based platform where people with an interest in accessibility can
|
||||
register and network with each other.
|
||||
|
||||
The group is hosting a launch event on the 28th November at the Council House,
|
||||
College Green, Bristol. Interested? More information is available at
|
||||
<http://www.accessiblebristol.org.uk/events/accessible-bristol-launch> or go to
|
||||
<http://buytickets.at/accessiblebristol/6434> to register.
|
||||
|
|
|
@ -11,9 +11,13 @@ tags:
|
|||
- drupal-planet
|
||||
- drupal
|
||||
---
|
||||
|
||||
How to use a date popup calendar within your custom module.
|
||||
|
||||
First, I need to download the [Date](http://drupal.org/project/date "Date module on Drupal.org") module, and make my module dependent on date_popup by adding the following line into my module's .info file.
|
||||
First, I need to download the
|
||||
[Date](http://drupal.org/project/date 'Date module on Drupal.org') module, and
|
||||
make my module dependent on date_popup by adding the following line into my
|
||||
module's .info file.
|
||||
|
||||
```language-ini
|
||||
dependencies[] = date_popup
|
||||
|
|
|
@ -10,25 +10,45 @@ tags:
|
|||
- sequal-pro
|
||||
- database
|
||||
---
|
||||
In preparation for my Blog posts being added to [Drupal Planet](http://drupal.org/planet), I needed to create a new Taxonomy term (or, in this case, tag) called 'Drupal Planet', and assign it to new content to imported into their aggregator. After taking a quick look though my previous posts, I decided that 14 of my previous posts were relevant, and thought that it would be useful to also assign these the 'Drupal Planet' tag.
|
||||
|
||||
I didn't want to manually open each post and add the new tag, so I decided to make the changes myself directly into the database using SQL, and as a follow-up to a previous post - [Quickly Change the Content Type of Multiple Nodes using SQL](/blog/change-content-type-multiple-nodes-using-sql/).
|
||||
In preparation for my Blog posts being added to
|
||||
[Drupal Planet](http://drupal.org/planet), I needed to create a new Taxonomy
|
||||
term (or, in this case, tag) called 'Drupal Planet', and assign it to new
|
||||
content to imported into their aggregator. After taking a quick look though my
|
||||
previous posts, I decided that 14 of my previous posts were relevant, and
|
||||
thought that it would be useful to also assign these the 'Drupal Planet' tag.
|
||||
|
||||
**Again, before changing any values within the database, ensure that you have an up-to-date backup which you can restore if you encounter a problem!**
|
||||
I didn't want to manually open each post and add the new tag, so I decided to
|
||||
make the changes myself directly into the database using SQL, and as a follow-up
|
||||
to a previous post -
|
||||
[Quickly Change the Content Type of Multiple Nodes using SQL](/blog/change-content-type-multiple-nodes-using-sql/).
|
||||
|
||||
The first thing I did was create the 'Drupal Planet' term in my Tags vocabulary. I decided to do this via the administration area of my site, and not via the database. Then, using [Sequel Pro](http://www.sequelpro.com), I ran the following SQL query to give me a list of Blog posts on my site - showing just their titles and nid values.
|
||||
**Again, before changing any values within the database, ensure that you have an
|
||||
up-to-date backup which you can restore if you encounter a problem!**
|
||||
|
||||
The first thing I did was create the 'Drupal Planet' term in my Tags vocabulary.
|
||||
I decided to do this via the administration area of my site, and not via the
|
||||
database. Then, using [Sequel Pro](http://www.sequelpro.com), I ran the
|
||||
following SQL query to give me a list of Blog posts on my site - showing just
|
||||
their titles and nid values.
|
||||
|
||||
```language-sql
|
||||
SELECT title, nid FROM node WHERE TYPE = 'blog' ORDER BY title ASC;
|
||||
```
|
||||
|
||||
I made a note of the nid's of the returned nodes, and kept them for later. I then ran a similar query against the term_data table. This returned a list of Taxonomy terms - showing the term's name, and it's unique tid value.
|
||||
I made a note of the nid's of the returned nodes, and kept them for later. I
|
||||
then ran a similar query against the term_data table. This returned a list of
|
||||
Taxonomy terms - showing the term's name, and it's unique tid value.
|
||||
|
||||
```language-sql
|
||||
SELECT NAME, tid FROM term_data ORDER BY NAME ASC;
|
||||
```
|
||||
|
||||
The term that I was interested in, Drupal Planet, had the tid of 84. To confirm that no nodes were already assigned a taxonomy term with this tid, I ran another query against the database. I'm using aliases within this query to link the node, term_node and term_data tables. For more information on SQL aliases, take a look at <http://w3schools.com/sql/sql_alias.asp>.
|
||||
The term that I was interested in, Drupal Planet, had the tid of 84. To confirm
|
||||
that no nodes were already assigned a taxonomy term with this tid, I ran another
|
||||
query against the database. I'm using aliases within this query to link the
|
||||
node, term_node and term_data tables. For more information on SQL aliases, take
|
||||
a look at <http://w3schools.com/sql/sql_alias.asp>.
|
||||
|
||||
```language-sql
|
||||
SELECT * FROM node n, term_data td, term_node tn WHERE td.tid = 84 AND n.nid = tn.nid AND tn.tid = td.tid;
|
||||
|
@ -36,14 +56,24 @@ SELECT * FROM node n, term_data td, term_node tn WHERE td.tid = 84 AND n.nid = t
|
|||
|
||||
As expected, it returned no rows.
|
||||
|
||||
The table that links node and term_data is called term_node, and is made up of the nid and vid columns from the node table, as well as the tid column from the term_data table. Is it is here that the additional rows would need to be entered.
|
||||
The table that links node and term_data is called term_node, and is made up of
|
||||
the nid and vid columns from the node table, as well as the tid column from the
|
||||
term_data table. Is it is here that the additional rows would need to be
|
||||
entered.
|
||||
|
||||
To confirm everything, I ran a simple query against an old post. I know that the only taxonomy term associated with this post is 'Personal', which has a tid value of 44.
|
||||
To confirm everything, I ran a simple query against an old post. I know that the
|
||||
only taxonomy term associated with this post is 'Personal', which has a tid
|
||||
value of 44.
|
||||
|
||||
```language-sql
|
||||
SELECT nid, tid FROM term_node WHERE nid = 216;
|
||||
```
|
||||
|
||||
Once the query had confirmed the correct tid value, I began to write the SQL Insert statement that would be needed to add the new term to the required nodes. The nid and vid values were the same on each node, and the value of my taxonomy term would need to be 84.
|
||||
Once the query had confirmed the correct tid value, I began to write the SQL
|
||||
Insert statement that would be needed to add the new term to the required nodes.
|
||||
The nid and vid values were the same on each node, and the value of my taxonomy
|
||||
term would need to be 84.
|
||||
|
||||
Once this had completed with no errors, I returned to the administration area of my Drupal site to confirm whether or not the nodes had been assigned the new term.
|
||||
Once this had completed with no errors, I returned to the administration area of
|
||||
my Drupal site to confirm whether or not the nodes had been assigned the new
|
||||
term.
|
||||
|
|
|
@ -2,14 +2,24 @@
|
|||
title: Adding Custom Theme Templates in Drupal 7
|
||||
date: 2012-04-19
|
||||
excerpt: >
|
||||
Today, I had a situation where I was displaying a list of teasers for news article nodes. The article content type had several different fields assigned to it, including main and thumbnail images. In this case, I wanted to have different output and fields displayed when a teaser was displayed compared to when a complete node was displayed.
|
||||
Today, I had a situation where I was displaying a list of teasers for news
|
||||
article nodes. The article content type had several different fields assigned
|
||||
to it, including main and thumbnail images. In this case, I wanted to have
|
||||
different output and fields displayed when a teaser was displayed compared to
|
||||
when a complete node was displayed.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupal
|
||||
---
|
||||
Today, I had a situation where I was displaying a list of teasers for news article nodes. The article content type had several different fields assigned to it, including main and thumbnail images. In this case, I wanted to have different output and fields displayed when a teaser was displayed compared to when a complete node was displayed.
|
||||
|
||||
I have previously seen it done this way by adding this into in a node.tpl.php file:
|
||||
Today, I had a situation where I was displaying a list of teasers for news
|
||||
article nodes. The article content type had several different fields assigned to
|
||||
it, including main and thumbnail images. In this case, I wanted to have
|
||||
different output and fields displayed when a teaser was displayed compared to
|
||||
when a complete node was displayed.
|
||||
|
||||
I have previously seen it done this way by adding this into in a node.tpl.php
|
||||
file:
|
||||
|
||||
```language-php
|
||||
if ($teaser) {
|
||||
|
@ -20,9 +30,15 @@ else {
|
|||
}
|
||||
```
|
||||
|
||||
However, I decided to do something different and create a separate template file just for teasers. This is done using the hook_preprocess_HOOK function that I can add into my theme's template.php file.
|
||||
However, I decided to do something different and create a separate template file
|
||||
just for teasers. This is done using the hook_preprocess_HOOK function that I
|
||||
can add into my theme's template.php file.
|
||||
|
||||
The function requires the node variables as an argument - one of which is theme_hook_suggestions. This is an array of suggested template files that Drupal looks for and attempts to use when displaying a node, and this is where I'll be adding a new suggestion for my teaser-specific template. Using the `debug()` function, I can easily see what's already there.
|
||||
The function requires the node variables as an argument - one of which is
|
||||
theme_hook_suggestions. This is an array of suggested template files that Drupal
|
||||
looks for and attempts to use when displaying a node, and this is where I'll be
|
||||
adding a new suggestion for my teaser-specific template. Using the `debug()`
|
||||
function, I can easily see what's already there.
|
||||
|
||||
```language-php
|
||||
array (
|
||||
|
@ -41,7 +57,7 @@ So, within my theme's template.php file:
|
|||
*/
|
||||
function mytheme_preprocess_node(&$variables) {
|
||||
$node = $variables['node'];
|
||||
|
||||
|
||||
if ($variables['teaser']) {
|
||||
// Add a new item into the theme_hook_suggestions array.
|
||||
$variables['theme_hook_suggestions'][] = 'node__' . $node->type . '_teaser';
|
||||
|
@ -61,4 +77,8 @@ array (
|
|||
)
|
||||
```
|
||||
|
||||
Now, within my theme I can create a new node--article-teaser.tpl.php template file and this will get called instead of the node--article.tpl.php when a teaser is loaded. As I'm not specifying the node type specifically and using the dynamic <em>$node->type</em> value within my suggestion, this will also apply for all other content types on my site and not just news articles.
|
||||
Now, within my theme I can create a new node--article-teaser.tpl.php template
|
||||
file and this will get called instead of the node--article.tpl.php when a teaser
|
||||
is loaded. As I'm not specifying the node type specifically and using the
|
||||
dynamic <em>\$node->type</em> value within my suggestion, this will also apply
|
||||
for all other content types on my site and not just news articles.
|
||||
|
|
|
@ -1,59 +1,97 @@
|
|||
---
|
||||
title: Announcing the Drupal VM Generator
|
||||
date: 2016-02-15
|
||||
excerpt: For the past few weeks, I’ve been working on a personal side project based on Drupal VM - the Drupal VM Generator.
|
||||
excerpt:
|
||||
For the past few weeks, I’ve been working on a personal side project based on
|
||||
Drupal VM - the Drupal VM Generator.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- drupal-vm
|
||||
- drupal-vm-generator
|
||||
- symfony
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- drupal-vm
|
||||
- drupal-vm-generator
|
||||
- symfony
|
||||
---
|
||||
For the past few weeks, I’ve been working on a personal side project based on Drupal VM. It’s called the [Drupal VM Generator][1], and over the weekend I’ve added the final features and fixed the remaining issues, and tagged the 1.0.0 release.
|
||||
|
||||
For the past few weeks, I’ve been working on a personal side project based on
|
||||
Drupal VM. It’s called the [Drupal VM Generator][1], and over the weekend I’ve
|
||||
added the final features and fixed the remaining issues, and tagged the 1.0.0
|
||||
release.
|
||||
|
||||
![](/images/blog/drupalvm-generate-repo.png)
|
||||
|
||||
## What is Drupal VM?
|
||||
|
||||
[Drupal VM][2] is a project created and maintained by [Jeff Geerling][3]. It’s a [Vagrant][4] virtual machine for Drupal development that is provisioned using [Ansible][5].
|
||||
[Drupal VM][2] is a project created and maintained by [Jeff Geerling][3]. It’s a
|
||||
[Vagrant][4] virtual machine for Drupal development that is provisioned using
|
||||
[Ansible][5].
|
||||
|
||||
What is different to a regular Vagrant VM is that uses a file called `config.yml` to configure the machine. Settings such as `vagrant_hostname`, `drupalvm_webserver` and `drupal_core_path` are stored as YAML and passed into the `Vagrantfile` and the `playbook.yml` file which is used when the Ansible provisioner runs.
|
||||
What is different to a regular Vagrant VM is that uses a file called
|
||||
`config.yml` to configure the machine. Settings such as `vagrant_hostname`,
|
||||
`drupalvm_webserver` and `drupal_core_path` are stored as YAML and passed into
|
||||
the `Vagrantfile` and the `playbook.yml` file which is used when the Ansible
|
||||
provisioner runs.
|
||||
|
||||
In addition to some essential Ansible roles for installing and configuring packages such as Git, MySQL, PHP and Drush, there are also some roles that are conditional and only installed based on the value of other settings. These include Apache, Nginx, Solr, Varnish and Drupal Console.
|
||||
In addition to some essential Ansible roles for installing and configuring
|
||||
packages such as Git, MySQL, PHP and Drush, there are also some roles that are
|
||||
conditional and only installed based on the value of other settings. These
|
||||
include Apache, Nginx, Solr, Varnish and Drupal Console.
|
||||
|
||||
## What does the Drupal VM Generator do?
|
||||
|
||||
> The Drupal VM Generator is a Symfony application that allows you to quickly create configuration files that are minimal and use-case specific.
|
||||
> The Drupal VM Generator is a Symfony application that allows you to quickly
|
||||
> create configuration files that are minimal and use-case specific.
|
||||
|
||||
Drupal VM comes with an [example.config.yml file][6] that shows all of the default variables and their values. When I first started using it, I’d make a copy of `example.config.yml`, rename it to `config.yml` and edit it as needed, but a lot of the examples aren’t needed for every use case. If you’re using Nginx as your webserver, then you don’t need the Apache virtual hosts. If you are not using Solr on this project, then you don’t need the Solr variables.
|
||||
Drupal VM comes with an [example.config.yml file][6] that shows all of the
|
||||
default variables and their values. When I first started using it, I’d make a
|
||||
copy of `example.config.yml`, rename it to `config.yml` and edit it as needed,
|
||||
but a lot of the examples aren’t needed for every use case. If you’re using
|
||||
Nginx as your webserver, then you don’t need the Apache virtual hosts. If you
|
||||
are not using Solr on this project, then you don’t need the Solr variables.
|
||||
|
||||
For a few months, I’ve kept and used boilerplace versions of `config.yml` - one for Apache and one for Nginx. These are minimal, so have most of the comments removed and only the variables that I regularly need, but these can still be quite time consuming to edit each time, and if there are additions or changes upstream, then I have two versions to maintain.
|
||||
For a few months, I’ve kept and used boilerplace versions of `config.yml` - one
|
||||
for Apache and one for Nginx. These are minimal, so have most of the comments
|
||||
removed and only the variables that I regularly need, but these can still be
|
||||
quite time consuming to edit each time, and if there are additions or changes
|
||||
upstream, then I have two versions to maintain.
|
||||
|
||||
The Drupal VM Generator is a Symfony application that allows you to quickly create configuration files that are minimal and use-case specific. It uses the [Console component][7] to collect input from the user, [Twig][8] to generate the file, the [Filesystem component][9] to write it.
|
||||
The Drupal VM Generator is a Symfony application that allows you to quickly
|
||||
create configuration files that are minimal and use-case specific. It uses the
|
||||
[Console component][7] to collect input from the user, [Twig][8] to generate the
|
||||
file, the [Filesystem component][9] to write it.
|
||||
|
||||
Based on the options passed to it and/or answers that you provide, it generates a custom, minimal `config.yml` file for your project.
|
||||
Based on the options passed to it and/or answers that you provide, it generates
|
||||
a custom, minimal `config.yml` file for your project.
|
||||
|
||||
Here’s an example of it in action:
|
||||
|
||||
!['An animated gif showing the interaction process and the resulting config.yml file'](/images/blog/drupalvm-generate-example-2.gif)
|
||||
|
||||
You can also define options when calling the command and skip any or all questions. Running the following would bypass all of the questions and create a new file with no interaction or additional steps.
|
||||
You can also define options when calling the command and skip any or all
|
||||
questions. Running the following would bypass all of the questions and create a
|
||||
new file with no interaction or additional steps.
|
||||
|
||||
{{ gist('24e569577ca4b72f049d', 'with-options.sh') }}
|
||||
|
||||
## Where do I get it?
|
||||
|
||||
The project is hosted on [GitHub][1], and there are installation instructions within the [README][10].
|
||||
The project is hosted on [GitHub][1], and there are installation instructions
|
||||
within the [README][10].
|
||||
|
||||
<div class="github-card" data-github="opdavies/drupal-vm-generator" data-width="400" data-height="" data-theme="default"></div>
|
||||
|
||||
The recommended method is via downloading the phar file (the same as Composer and Drupal Console). You can also clone the GitHub repository and run the command from there. I’m also wanting to upload it to Packagist so that it can be included if you manage your projects with Composer.
|
||||
The recommended method is via downloading the phar file (the same as Composer
|
||||
and Drupal Console). You can also clone the GitHub repository and run the
|
||||
command from there. I’m also wanting to upload it to Packagist so that it can be
|
||||
included if you manage your projects with Composer.
|
||||
|
||||
Please log any bugs or feature requests in the [GitHub issue tracker][11], and I’m more than happy to receive pull requests.
|
||||
Please log any bugs or feature requests in the [GitHub issue tracker][11], and
|
||||
I’m more than happy to receive pull requests.
|
||||
|
||||
If you’re interested in contributing, please feel free to fork the repository and start doing so, or contact me with any questions.
|
||||
If you’re interested in contributing, please feel free to fork the repository
|
||||
and start doing so, or contact me with any questions.
|
||||
|
||||
__Update 17/02/16:__ The autoloading issue is now fixed if you require the package via Composer, and this has been tagged as the [1.0.1 release][12]
|
||||
**Update 17/02/16:** The autoloading issue is now fixed if you require the
|
||||
package via Composer, and this has been tagged as the [1.0.1 release][12]
|
||||
|
||||
[1]: https://github.com/opdavies/drupal-vm-generator
|
||||
[2]: http://www.drupalvm.com
|
||||
|
@ -64,6 +102,7 @@ __Update 17/02/16:__ The autoloading issue is now fixed if you require the packa
|
|||
[7]: http://symfony.com/doc/current/components/console/introduction.html
|
||||
[8]: http://twig.sensiolabs.org
|
||||
[9]: http://symfony.com/doc/current/components/filesystem/introduction.html
|
||||
[10]: https://github.com/opdavies/drupal-vm-generator/blob/master/README.md#installation
|
||||
[10]:
|
||||
https://github.com/opdavies/drupal-vm-generator/blob/master/README.md#installation
|
||||
[11]: https://github.com/opdavies/drupal-vm-generator/issues
|
||||
[12]: https://github.com/opdavies/drupal-vm-generator/releases/tag/1.0.1
|
||||
|
|
|
@ -3,40 +3,69 @@ title: Automating Sculpin Builds with Jenkins CI
|
|||
date: 2015-07-21
|
||||
excerpt: How to use Jenkins to automate building Sculpin websites.
|
||||
tags:
|
||||
- sculpin
|
||||
- jenkins
|
||||
- sculpin
|
||||
- jenkins
|
||||
---
|
||||
As part of re-building this site with [Sculpin](http://sculpin.io), I wanted to automate the deployments, as in I wouldn't need to run a script like [publish.sh](https://raw.githubusercontent.com/sculpin/sculpin-blog-skeleton/master/publish.sh) locally and have that deploy my code onto my server. Not only did that mean that my local workflow was simpler (update, commit and push, rather than update, commit, push and deploy), but if I wanted to make a quick edit or hotfix, I could log into GitHub or Bitbucket (wherever I decided to host the source code) from any computer or my phone, make the change and have it deployed for me.
|
||||
|
||||
I'd started using [Jenkins CI](http://jenkins-ci.org) during my time at the Drupal Association, and had since built my own Jenkins server to handle deployments of Drupal websites, so that was the logical choice to use.
|
||||
As part of re-building this site with [Sculpin](http://sculpin.io), I wanted to
|
||||
automate the deployments, as in I wouldn't need to run a script like
|
||||
[publish.sh](https://raw.githubusercontent.com/sculpin/sculpin-blog-skeleton/master/publish.sh)
|
||||
locally and have that deploy my code onto my server. Not only did that mean that
|
||||
my local workflow was simpler (update, commit and push, rather than update,
|
||||
commit, push and deploy), but if I wanted to make a quick edit or hotfix, I
|
||||
could log into GitHub or Bitbucket (wherever I decided to host the source code)
|
||||
from any computer or my phone, make the change and have it deployed for me.
|
||||
|
||||
I'd started using [Jenkins CI](http://jenkins-ci.org) during my time at the
|
||||
Drupal Association, and had since built my own Jenkins server to handle
|
||||
deployments of Drupal websites, so that was the logical choice to use.
|
||||
|
||||
## Installing Jenkins and Sculpin
|
||||
|
||||
If you don’t already have Jenkins installed and configured, I'd suggest using [Jeff Geerling](http://jeffgeerling.com/) (aka geerlingguy)'s [Ansible role for Jenkins CI](https://galaxy.ansible.com/list#/roles/440).
|
||||
If you don’t already have Jenkins installed and configured, I'd suggest using
|
||||
[Jeff Geerling](http://jeffgeerling.com/) (aka geerlingguy)'s
|
||||
[Ansible role for Jenkins CI](https://galaxy.ansible.com/list#/roles/440).
|
||||
|
||||
I've also released an [Ansible role for Sculpin](https://galaxy.ansible.com/list#/roles/4063) that installs the executable so that the Jenkins server can run Sculpin commands.
|
||||
I've also released an
|
||||
[Ansible role for Sculpin](https://galaxy.ansible.com/list#/roles/4063) that
|
||||
installs the executable so that the Jenkins server can run Sculpin commands.
|
||||
|
||||
## Triggering a Build from a Git Commit
|
||||
|
||||
I created a new Jenkins item for this task, and restricted where it could be run to `master` (i.e. the Jenkins server rather than any of the nodes).
|
||||
I created a new Jenkins item for this task, and restricted where it could be run
|
||||
to `master` (i.e. the Jenkins server rather than any of the nodes).
|
||||
|
||||
### Polling from Git
|
||||
|
||||
I entered the url to the [GitHub repo](https://github.com/opdavies/oliverdavies.uk) into the **Source Code Management** section (the Git option *may* have been added by the [Git plugin](https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin) that I have installed).
|
||||
I entered the url to the
|
||||
[GitHub repo](https://github.com/opdavies/oliverdavies.uk) into the **Source
|
||||
Code Management** section (the Git option _may_ have been added by the
|
||||
[Git plugin](https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin) that I have
|
||||
installed).
|
||||
|
||||
As we don’t need any write access back to the repo, using the HTTP URL rather than the SSH one was fine, and I didn’t need to provide any additional credentials.
|
||||
As we don’t need any write access back to the repo, using the HTTP URL rather
|
||||
than the SSH one was fine, and I didn’t need to provide any additional
|
||||
credentials.
|
||||
|
||||
Also, as I knew that I’d be working a lot with feature branches, I entered `*/master` as the only branch to build. This meant that pushing changes or making edits on any other branches would not trigger a build.
|
||||
Also, as I knew that I’d be working a lot with feature branches, I entered
|
||||
`*/master` as the only branch to build. This meant that pushing changes or
|
||||
making edits on any other branches would not trigger a build.
|
||||
|
||||
![Defining the Git repository in Jenkins](/images/blog/oliverdavies-uk-jenkins-git-repo.png)
|
||||
|
||||
I also checked the **Poll SCM** option so that Jenkins would be routinely checking for updated code. This essentially uses the same syntax as cron, specifying minutes, hours etc. I entered `* * * * *` so that Jenkins would poll each minute, knowing that I could make this less frequent if needed.
|
||||
I also checked the **Poll SCM** option so that Jenkins would be routinely
|
||||
checking for updated code. This essentially uses the same syntax as cron,
|
||||
specifying minutes, hours etc. I entered `* * * * *` so that Jenkins would poll
|
||||
each minute, knowing that I could make this less frequent if needed.
|
||||
|
||||
This now that Jenkins would be checking for any updates to the repo each minute, and could execute tasks if needed.
|
||||
This now that Jenkins would be checking for any updates to the repo each minute,
|
||||
and could execute tasks if needed.
|
||||
|
||||
### Building and Deploying
|
||||
|
||||
Within the **Builds** section of the item, I added an *Execute Shell* step, where I could enter a command to execute. Here, I pasted a modified version of the original publish.sh script.
|
||||
Within the **Builds** section of the item, I added an _Execute Shell_ step,
|
||||
where I could enter a command to execute. Here, I pasted a modified version of
|
||||
the original publish.sh script.
|
||||
|
||||
```language-bash
|
||||
#!/bin/bash
|
||||
|
@ -50,11 +79,18 @@ rsync -avze 'ssh' --delete output_prod/ prodwww2:/var/www/html/oliverdavies.uk/h
|
|||
if [ $? -ne 0 ]; then echo "Could not publish the site"; exit 1; fi
|
||||
```
|
||||
|
||||
This essentially is the same as the original file, in that Sculpin generates the site, and uses rsync to deploy it somewhere else. In my case, `prodwww2` is a Jenkins node (this alias is configured in `/var/lib/jenkins/.ssh/config`), and `/var/www/html/oliverdavies.uk/htdocs` is the directory from where my site is served.
|
||||
This essentially is the same as the original file, in that Sculpin generates the
|
||||
site, and uses rsync to deploy it somewhere else. In my case, `prodwww2` is a
|
||||
Jenkins node (this alias is configured in `/var/lib/jenkins/.ssh/config`), and
|
||||
`/var/www/html/oliverdavies.uk/htdocs` is the directory from where my site is
|
||||
served.
|
||||
|
||||
## Building Periodically
|
||||
|
||||
There is some dynamic content on my site, specifically on the Talks page. Each talk has a date assigned to it, and within the Twig template, the talk is positoned within upcoming or previous talks based on whether this date is less or greater than the time of the build.
|
||||
There is some dynamic content on my site, specifically on the Talks page. Each
|
||||
talk has a date assigned to it, and within the Twig template, the talk is
|
||||
positoned within upcoming or previous talks based on whether this date is less
|
||||
or greater than the time of the build.
|
||||
|
||||
The YAML front matter:
|
||||
|
||||
|
@ -81,23 +117,41 @@ The Twig layout:
|
|||
{%- endverbatim %}
|
||||
```
|
||||
|
||||
I also didn’t want to have to push an empty commit or manually trigger a job in Jenkins after doing a talk in order for it to be positioned in the correct place on the page, so I also wanted Jenkins to schedule a regular build regardless of whether or not code had been pushed, so ensure that my talks page would be up to date.
|
||||
I also didn’t want to have to push an empty commit or manually trigger a job in
|
||||
Jenkins after doing a talk in order for it to be positioned in the correct place
|
||||
on the page, so I also wanted Jenkins to schedule a regular build regardless of
|
||||
whether or not code had been pushed, so ensure that my talks page would be up to
|
||||
date.
|
||||
|
||||
After originally thinking that I'd have to split the build steps into a separate item and trigger that from a scheduled item, and amend my git commit item accordingly, I found a **Build periodically** option that I could use within the same item, leaving it intact and not having to make amends.
|
||||
After originally thinking that I'd have to split the build steps into a separate
|
||||
item and trigger that from a scheduled item, and amend my git commit item
|
||||
accordingly, I found a **Build periodically** option that I could use within the
|
||||
same item, leaving it intact and not having to make amends.
|
||||
|
||||
I set this to `@daily` (the same `H H * * *` - `H` is a Jenkins thing), so that the build would be triggered automatically each day without a commit, and deploy any updates to the site.
|
||||
I set this to `@daily` (the same `H H * * *` - `H` is a Jenkins thing), so that
|
||||
the build would be triggered automatically each day without a commit, and deploy
|
||||
any updates to the site.
|
||||
|
||||
![Setting Jenkins to periodically build a new version of the site.](/images/blog/oliverdavies-uk-jenkins-git-timer.png)
|
||||
|
||||
## Next Steps
|
||||
|
||||
This workflow works great for one site, but as I roll out more Sculpin sites, I'd like to reduce duplication. I see this mainly as I’ll end up creating a separate `sculpin_build` item that’s decoupled from the site that it’s building, and instead passing variables such as environment, server name and docroot path as parameters in a parameterized build.
|
||||
This workflow works great for one site, but as I roll out more Sculpin sites,
|
||||
I'd like to reduce duplication. I see this mainly as I’ll end up creating a
|
||||
separate `sculpin_build` item that’s decoupled from the site that it’s building,
|
||||
and instead passing variables such as environment, server name and docroot path
|
||||
as parameters in a parameterized build.
|
||||
|
||||
I'll probably also take the raw shell script out of Jenkins and save it in a text file that's stored locally on the server, and execute that via Jenkins. This means that I’d be able to store this file in a separate Git repository with my other Jenkins scripts and get the standard advantages of using version control.
|
||||
I'll probably also take the raw shell script out of Jenkins and save it in a
|
||||
text file that's stored locally on the server, and execute that via Jenkins.
|
||||
This means that I’d be able to store this file in a separate Git repository with
|
||||
my other Jenkins scripts and get the standard advantages of using version
|
||||
control.
|
||||
|
||||
## Update
|
||||
|
||||
Since publishing this post, I've added some more items to the original build script.
|
||||
Since publishing this post, I've added some more items to the original build
|
||||
script.
|
||||
|
||||
### Updating Composer
|
||||
|
||||
|
@ -107,7 +161,9 @@ if [ -f composer.json ]; then
|
|||
fi
|
||||
```
|
||||
|
||||
Updates project dependencies via [Composer](https://getcomposer.org/doc/00-intro.md#introduction) if composer.json exists.
|
||||
Updates project dependencies via
|
||||
[Composer](https://getcomposer.org/doc/00-intro.md#introduction) if
|
||||
composer.json exists.
|
||||
|
||||
### Updating Sculpin Dependencies
|
||||
|
||||
|
@ -117,7 +173,8 @@ if [ -f sculpin.json ]; then
|
|||
fi
|
||||
```
|
||||
|
||||
Runs `sculpin install` on each build if the sculpin.json file exists, to ensure that the required custom bundles and dependencies are installed.
|
||||
Runs `sculpin install` on each build if the sculpin.json file exists, to ensure
|
||||
that the required custom bundles and dependencies are installed.
|
||||
|
||||
### Managing Redirects
|
||||
|
||||
|
@ -127,4 +184,9 @@ if [ -f scripts/redirects.php ]; then
|
|||
fi
|
||||
```
|
||||
|
||||
I've been working on a `redirects.php` script that generates redirects from a .csv file, after seeing similar things in the [Pantheon Documentation](https://github.com/pantheon-systems/documentation) and [That Podcast](https://github.com/thatpodcast/thatpodcast.io) repositories. This checks if that file exists, and if so, runs it and generates the source file containing each redirect.
|
||||
I've been working on a `redirects.php` script that generates redirects from a
|
||||
.csv file, after seeing similar things in the
|
||||
[Pantheon Documentation](https://github.com/pantheon-systems/documentation) and
|
||||
[That Podcast](https://github.com/thatpodcast/thatpodcast.io) repositories. This
|
||||
checks if that file exists, and if so, runs it and generates the source file
|
||||
containing each redirect.
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
---
|
||||
title: Back to the future with Git’s diff and apply commands
|
||||
date: 2018-04-23
|
||||
excerpt: How to revert files using Git, but as a new commit to prevent force pushing.
|
||||
excerpt:
|
||||
How to revert files using Git, but as a new commit to prevent force pushing.
|
||||
tags:
|
||||
- git
|
||||
- git
|
||||
---
|
||||
This is one of those “there’s probably already a better way to do this” situations, but it worked.
|
||||
|
||||
I was having some issues this past weekend where, despite everything working fine locally, a server was showing a “500 Internal Server” after I pushed some changes to a site. In order to bring the site back online, I needed to revert the site files back to the previous version, but as part of a new commit.
|
||||
This is one of those “there’s probably already a better way to do this”
|
||||
situations, but it worked.
|
||||
|
||||
The `git reset` commands removed the interim commits which meant that I couldn’t push to the remote (force pushing, quite rightly, isn’t allowed for the production branch), and using `git revert` was resulting in merge conflicts in `composer.lock` that I’d rather have avoided if possible.
|
||||
I was having some issues this past weekend where, despite everything working
|
||||
fine locally, a server was showing a “500 Internal Server” after I pushed some
|
||||
changes to a site. In order to bring the site back online, I needed to revert
|
||||
the site files back to the previous version, but as part of a new commit.
|
||||
|
||||
The `git reset` commands removed the interim commits which meant that I couldn’t
|
||||
push to the remote (force pushing, quite rightly, isn’t allowed for the
|
||||
production branch), and using `git revert` was resulting in merge conflicts in
|
||||
`composer.lock` that I’d rather have avoided if possible.
|
||||
|
||||
This is what `git log --oneline -n 4` was outputting:
|
||||
|
||||
|
@ -24,14 +33,18 @@ fc058bb Add services.yml
|
|||
|
||||
## First Solution
|
||||
|
||||
My first solution was to use `git diff` to create a single patch file of all of the changes from the current point back to the original commit. In this case, I’m using `head~3` (four commits before `head`) as the original reference, I could have alternatively used a commit ID, tag or branch name.
|
||||
My first solution was to use `git diff` to create a single patch file of all of
|
||||
the changes from the current point back to the original commit. In this case,
|
||||
I’m using `head~3` (four commits before `head`) as the original reference, I
|
||||
could have alternatively used a commit ID, tag or branch name.
|
||||
|
||||
```
|
||||
git diff head head~3 > temp.patch
|
||||
git apply -v temp.patch
|
||||
```
|
||||
|
||||
With the files are back in the former state, I can remove the patch, add the files as a new commit and push them to the remote.
|
||||
With the files are back in the former state, I can remove the patch, add the
|
||||
files as a new commit and push them to the remote.
|
||||
|
||||
```
|
||||
rm temp.patch
|
||||
|
@ -41,16 +54,20 @@ git commit -m 'Back to the future'
|
|||
git push
|
||||
```
|
||||
|
||||
Although the files are back in their previous, working state, as this is a new commit with a new commit SHA reference, there is no issue with the remote rejecting the commit or needing to attempt to force push.
|
||||
Although the files are back in their previous, working state, as this is a new
|
||||
commit with a new commit SHA reference, there is no issue with the remote
|
||||
rejecting the commit or needing to attempt to force push.
|
||||
|
||||
## Second Solution
|
||||
|
||||
The second solution is just a shorter, cleaner version of the first!
|
||||
|
||||
Rather than creating a patch file and applying it, the output from `git diff` can be piped straight into `git apply`.
|
||||
Rather than creating a patch file and applying it, the output from `git diff`
|
||||
can be piped straight into `git apply`.
|
||||
|
||||
```
|
||||
git diff head~3 head | git apply -v
|
||||
```
|
||||
|
||||
This means that there’s only one command to run and no leftover patch file, and I can go ahead and add and commit the changes straight away.
|
||||
This means that there’s only one command to run and no leftover patch file, and
|
||||
I can go ahead and add and commit the changes straight away.
|
||||
|
|
|
@ -3,15 +3,22 @@ title: Building Gmail Filters with PHP
|
|||
date: 2016-07-15
|
||||
excerpt: How to use PHP to generate and export filters for Gmail.
|
||||
tags:
|
||||
- php
|
||||
- gmail
|
||||
- php
|
||||
- gmail
|
||||
promoted: true
|
||||
---
|
||||
Earlier this week I wrote a small PHP library called [GmailFilterBuilder][0] that allows you to write Gmail filters in PHP and export them to XML.
|
||||
|
||||
I was already aware of a Ruby library called [gmail-britta][1] that does the same thing, but a) I’m not that familiar with Ruby so the syntax wasn’t that natural to me - it’s been a while since I wrote any Puppet manifests, and b) it seemed like a interesting little project to work on one evening.
|
||||
Earlier this week I wrote a small PHP library called [GmailFilterBuilder][0]
|
||||
that allows you to write Gmail filters in PHP and export them to XML.
|
||||
|
||||
The library contains two classes - `GmailFilter` which is used to create each filter, and `GmailFilterBuilder` that parses the filters and generates the XML using a [Twig][2] template.
|
||||
I was already aware of a Ruby library called [gmail-britta][1] that does the
|
||||
same thing, but a) I’m not that familiar with Ruby so the syntax wasn’t that
|
||||
natural to me - it’s been a while since I wrote any Puppet manifests, and b) it
|
||||
seemed like a interesting little project to work on one evening.
|
||||
|
||||
The library contains two classes - `GmailFilter` which is used to create each
|
||||
filter, and `GmailFilterBuilder` that parses the filters and generates the XML
|
||||
using a [Twig][2] template.
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -35,17 +42,24 @@ $filters[] = Filter::create()
|
|||
new Builder($filters);
|
||||
```
|
||||
|
||||
In this case, an email from `example@test.com` would be archived, never marked as spam, and have a label of "Test" added to it.
|
||||
In this case, an email from `example@test.com` would be archived, never marked
|
||||
as spam, and have a label of "Test" added to it.
|
||||
|
||||
With this code written, and the GmailFilterBuilder library installed via Composer, I can run `php test.php` and have the XML written to the screen.
|
||||
With this code written, and the GmailFilterBuilder library installed via
|
||||
Composer, I can run `php test.php` and have the XML written to the screen.
|
||||
|
||||
This can also be written to a file - `php test.php > filters.xml` - which can then be imported into Gmail.
|
||||
This can also be written to a file - `php test.php > filters.xml` - which can
|
||||
then be imported into Gmail.
|
||||
|
||||
## Twig Extensions
|
||||
|
||||
I also added a custom Twig extension that I moved into a separate [twig-extensions][5] library so that I and other people can re-use it in other projects.
|
||||
I also added a custom Twig extension that I moved into a separate
|
||||
[twig-extensions][5] library so that I and other people can re-use it in other
|
||||
projects.
|
||||
|
||||
It’s a simple filter that accepts a boolean and returns `true` or `false` as a string, but meant that I could remove three ternary operators from the template and replace them with the `boolean_string` filter.
|
||||
It’s a simple filter that accepts a boolean and returns `true` or `false` as a
|
||||
string, but meant that I could remove three ternary operators from the template
|
||||
and replace them with the `boolean_string` filter.
|
||||
|
||||
Before:
|
||||
|
||||
|
@ -63,7 +77,8 @@ After:
|
|||
```
|
||||
</div>
|
||||
|
||||
This can then be used to generate output like this, whereas having blank values would have resulted in errors when importing to Gmail.
|
||||
This can then be used to generate output like this, whereas having blank values
|
||||
would have resulted in errors when importing to Gmail.
|
||||
|
||||
```language-xml
|
||||
<apps:property name='shouldArchive' value='true'/>
|
||||
|
@ -75,9 +90,9 @@ For a working example, see my personal [gmail-filters][3] repository on GitHub.
|
|||
|
||||
## Resources
|
||||
|
||||
* [The GmailFilterBuilder library on Packagist][4]
|
||||
* [My Gmail filters on GitHub][3]
|
||||
* [My Twig Extensions on Packagist][5]
|
||||
- [The GmailFilterBuilder library on Packagist][4]
|
||||
- [My Gmail filters on GitHub][3]
|
||||
- [My Twig Extensions on Packagist][5]
|
||||
|
||||
[0]: https://github.com/opdavies/gmail-filter-builder
|
||||
[1]: https://github.com/antifuchs/gmail-britta
|
||||
|
|
|
@ -1,24 +1,35 @@
|
|||
---
|
||||
title: Building the new PHPSW Website
|
||||
date: 2018-02-28
|
||||
excerpt: Earlier this week we had another hack night, working on the new PHPSW user group website.
|
||||
excerpt:
|
||||
Earlier this week we had another hack night, working on the new PHPSW user
|
||||
group website.
|
||||
tags:
|
||||
- phpsw
|
||||
- symfony
|
||||
- tailwind-css
|
||||
- phpsw
|
||||
- symfony
|
||||
- tailwind-css
|
||||
has_tweets: true
|
||||
---
|
||||
Earlier this week we had another hack night, working on the new [PHPSW user group][0] website.
|
||||
|
||||
Earlier this week we had another hack night, working on the new [PHPSW user
|
||||
group][0] website.
|
||||
|
||||
<div class="mb-4">
|
||||
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Hacking away on the new <a href="https://twitter.com/phpsw?ref_src=twsrc%5Etfw">@phpsw</a> website with <a href="https://twitter.com/DaveLiddament?ref_src=twsrc%5Etfw">@DaveLiddament</a> and <a href="https://twitter.com/kasiazien?ref_src=twsrc%5Etfw">@kasiazien</a>. <a href="https://t.co/kmfjdQSOUq">pic.twitter.com/kmfjdQSOUq</a></p>— Oliver Davies (@opdavies) <a href="https://twitter.com/opdavies/status/968224364129906688?ref_src=twsrc%5Etfw">February 26, 2018</a></blockquote>
|
||||
</div>
|
||||
|
||||
It’s built with Symfony so it’s naturally using Twig for templating. I’ve become a big fan of the utility based approach to CSS and [Tailwind CSS][1] in particular, so I’m using that for all of the styling, and using [Webpack Encore][2] to compile all of the assets.
|
||||
It’s built with Symfony so it’s naturally using Twig for templating. I’ve become
|
||||
a big fan of the utility based approach to CSS and [Tailwind CSS][1] in
|
||||
particular, so I’m using that for all of the styling, and using [Webpack
|
||||
Encore][2] to compile all of the assets.
|
||||
|
||||
We have an integration with Meetup.com which we’re using to pull all of our previous event data and store them as JSON files for Symfony to parse and render, which it then uses to generate static HTML to upload onto the server.
|
||||
We have an integration with Meetup.com which we’re using to pull all of our
|
||||
previous event data and store them as JSON files for Symfony to parse and
|
||||
render, which it then uses to generate static HTML to upload onto the server.
|
||||
|
||||
We’re in the process of populating all of the past data, but look out for a v1 launch soon. In the meantime, feel free to take a peek at our [GitHub repository][3].
|
||||
We’re in the process of populating all of the past data, but look out for a v1
|
||||
launch soon. In the meantime, feel free to take a peek at our [GitHub
|
||||
repository][3].
|
||||
|
||||
[0]: https://phpsw.uk
|
||||
[1]: https://tailwindcss.com
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
---
|
||||
title: Change the Content Type of Multiple Nodes Using SQL
|
||||
date: 2010-07-01
|
||||
excerpt: In this post, I will be changing values within my Drupal 6 site's database to quickly change the content type of multiple nodes.
|
||||
excerpt:
|
||||
In this post, I will be changing values within my Drupal 6 site's database to
|
||||
quickly change the content type of multiple nodes.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupal-6
|
||||
|
@ -11,16 +13,31 @@ tags:
|
|||
- database
|
||||
- content-types
|
||||
---
|
||||
In this post, I will be changing values within my Drupal 6 site's database to quickly change the content type of multiple nodes. I will be using a test development site with the core Blog module installed, and converting Blog posts to a custom content type called 'News article'.
|
||||
|
||||
**Before changing any values within the database, ensure that you have an up-to-date backup which you can restore if you encounter a problem!**
|
||||
In this post, I will be changing values within my Drupal 6 site's database to
|
||||
quickly change the content type of multiple nodes. I will be using a test
|
||||
development site with the core Blog module installed, and converting Blog posts
|
||||
to a custom content type called 'News article'.
|
||||
|
||||
To begin with, I created the 'News article' content type, and then used the Devel Generate module to generate some Blog nodes.
|
||||
**Before changing any values within the database, ensure that you have an
|
||||
up-to-date backup which you can restore if you encounter a problem!**
|
||||
|
||||
Using [Sequel Pro](http://www.sequelpro.com), I can query the database to view the Blog posts (you can also do this via the [Terminal](http://guides.macrumors.com/Terminal) in a Mac OS X/Linux, [Oracle SQL Developer](http://www.oracle.com/technology/software/products/sql/index.html) on Windows, or directly within [phpMyAdmin](http://www.phpmyadmin.net/home_page/index.php)):
|
||||
To begin with, I created the 'News article' content type, and then used the
|
||||
Devel Generate module to generate some Blog nodes.
|
||||
|
||||
Using an SQL 'Update' command, I can change the type value from 'blog' to 'article'. This will change every occurance of the value 'blog'. If I wanted to only change certain nodes, I could add a 'Where' clause to only affect nodes with a certain nid or title.
|
||||
Using [Sequel Pro](http://www.sequelpro.com), I can query the database to view
|
||||
the Blog posts (you can also do this via the
|
||||
[Terminal](http://guides.macrumors.com/Terminal) in a Mac OS X/Linux,
|
||||
[Oracle SQL Developer](http://www.oracle.com/technology/software/products/sql/index.html)
|
||||
on Windows, or directly within
|
||||
[phpMyAdmin](http://www.phpmyadmin.net/home_page/index.php)):
|
||||
|
||||
Using an SQL 'Update' command, I can change the type value from 'blog' to
|
||||
'article'. This will change every occurance of the value 'blog'. If I wanted to
|
||||
only change certain nodes, I could add a 'Where' clause to only affect nodes
|
||||
with a certain nid or title.
|
||||
|
||||
Now, when I query the database, the type is shown as 'article'.
|
||||
|
||||
Now, when I go back into the administration section of my site and view the content, the content type now shows at 'News article'.
|
||||
Now, when I go back into the administration section of my site and view the
|
||||
content, the content type now shows at 'News article'.
|
||||
|
|
|
@ -9,7 +9,10 @@ tags:
|
|||
- drupal-planet
|
||||
- php
|
||||
---
|
||||
I see this regularly when working on Drupal sites when someone wants to check whether the current user is logged in to Drupal (authenticated) or not (anonymous).
|
||||
|
||||
I see this regularly when working on Drupal sites when someone wants to check
|
||||
whether the current user is logged in to Drupal (authenticated) or not
|
||||
(anonymous).
|
||||
|
||||
```language-php
|
||||
global $user;
|
||||
|
@ -27,7 +30,9 @@ if (!$user->uid) {
|
|||
}
|
||||
```
|
||||
|
||||
The better way to do this is to use the [user_is_logged_in()](http://api.drupal.org/api/drupal/modules!user!user.module/function/user_is_logged_in/7) function.
|
||||
The better way to do this is to use the
|
||||
[user_is_logged_in()](http://api.drupal.org/api/drupal/modules!user!user.module/function/user_is_logged_in/7)
|
||||
function.
|
||||
|
||||
```language-php
|
||||
if (user_is_logged_in()) {
|
||||
|
@ -35,9 +40,12 @@ if (user_is_logged_in()) {
|
|||
}
|
||||
```
|
||||
|
||||
This returns a boolean (TRUE or FALSE) depending or not the user is logged in. Essentially, it does the same thing as the first example, but there's no need to load the global variable.
|
||||
This returns a boolean (TRUE or FALSE) depending or not the user is logged in.
|
||||
Essentially, it does the same thing as the first example, but there's no need to
|
||||
load the global variable.
|
||||
|
||||
A great use case for this is within a `hook_menu()` implementation within a custom module.
|
||||
A great use case for this is within a `hook_menu()` implementation within a
|
||||
custom module.
|
||||
|
||||
```language-php
|
||||
/**
|
||||
|
@ -54,4 +62,7 @@ function mymodule_menu() {
|
|||
}
|
||||
```
|
||||
|
||||
There is also a [user_is_anonymous()](http://api.drupal.org/api/drupal/modules!user!user.module/function/user_is_anonymous/7) function if you want the opposite result. Both of these functions are available in Drupal 6 and higher.
|
||||
There is also a
|
||||
[user_is_anonymous()](http://api.drupal.org/api/drupal/modules!user!user.module/function/user_is_anonymous/7)
|
||||
function if you want the opposite result. Both of these functions are available
|
||||
in Drupal 6 and higher.
|
||||
|
|
|
@ -6,6 +6,7 @@ tags:
|
|||
- svn
|
||||
- version-control
|
||||
---
|
||||
|
||||
How to checkout a specific revision from a SVN (Subversion) repository.
|
||||
|
||||
If you're checking out the repository for the first time:
|
||||
|
|
|
@ -1,19 +1,29 @@
|
|||
---
|
||||
title: Conditional Email Addresses in a Webform
|
||||
date: 2010-05-06
|
||||
excerpt: How to send webform emails to a different email address based on another field.
|
||||
excerpt:
|
||||
How to send webform emails to a different email address based on another
|
||||
field.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupal-6
|
||||
- conditional-email
|
||||
- webform
|
||||
---
|
||||
I created a new Webform to serve as a simple Contact form, but left the main configuration until after I created the form components. I added 'Name', 'Email', 'Subject' and 'Message' fields, as well as a 'Category' select list. Below 'Options', I entered each of my desired options in the following format:
|
||||
|
||||
I created a new Webform to serve as a simple Contact form, but left the main
|
||||
configuration until after I created the form components. I added 'Name',
|
||||
'Email', 'Subject' and 'Message' fields, as well as a 'Category' select list.
|
||||
Below 'Options', I entered each of my desired options in the following format:
|
||||
|
||||
```language-ini
|
||||
Email address|Visible name
|
||||
```
|
||||
|
||||
I went back to the form configuration page and expanded 'Conditional Email Recipients', and selected my Category. Note that the standard 'Email To' field above it needs to be empty. Originally, I made the mistake of leaving addresses in that field which resulted in people being sent emails regardles of which category was selected. I then configured the rest of the form.
|
||||
I went back to the form configuration page and expanded 'Conditional Email
|
||||
Recipients', and selected my Category. Note that the standard 'Email To' field
|
||||
above it needs to be empty. Originally, I made the mistake of leaving addresses
|
||||
in that field which resulted in people being sent emails regardles of which
|
||||
category was selected. I then configured the rest of the form.
|
||||
|
||||
Then, when I went to the finished form, the category selection was available.
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
---
|
||||
title: Configuring the Reroute Email Module
|
||||
date: 2014-12-22
|
||||
excerpt: How to configure the Reroute Email module, to prevent sending emails to real users from your pre-production sites!
|
||||
excerpt:
|
||||
How to configure the Reroute Email module, to prevent sending emails to real
|
||||
users from your pre-production sites!
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-6
|
||||
|
@ -10,33 +12,50 @@ tags:
|
|||
- email
|
||||
draft: true
|
||||
---
|
||||
[Reroute Email](https://www.drupal.org/project/reroute_email) module uses `hook_mail_alter()` to prevent emails from being sent to users from non-production sites. It allows you to enter one or more email addresses that will receive the emails instead of delivering them to the original user.
|
||||
|
||||
> This is useful in case where you do not want email sent from a Drupal site to reach the users. For example, if you copy a live site to a test site for the purpose of development, and you do not want any email sent to real users of the original site. Or you want to check the emails sent for uniform formatting, footers, ...etc.
|
||||
[Reroute Email](https://www.drupal.org/project/reroute_email) module uses
|
||||
`hook_mail_alter()` to prevent emails from being sent to users from
|
||||
non-production sites. It allows you to enter one or more email addresses that
|
||||
will receive the emails instead of delivering them to the original user.
|
||||
|
||||
As we don't need the module configured on production (we don't need to reroute any emails there), it's best to do this in code using settings.local.php (if you have one) or the standard settings.php file.
|
||||
> This is useful in case where you do not want email sent from a Drupal site to
|
||||
> reach the users. For example, if you copy a live site to a test site for the
|
||||
> purpose of development, and you do not want any email sent to real users of
|
||||
> the original site. Or you want to check the emails sent for uniform
|
||||
> formatting, footers, ...etc.
|
||||
|
||||
The first thing that we need to do is to enable rerouting. Without doing this, nothing will happen.
|
||||
As we don't need the module configured on production (we don't need to reroute
|
||||
any emails there), it's best to do this in code using settings.local.php (if you
|
||||
have one) or the standard settings.php file.
|
||||
|
||||
The first thing that we need to do is to enable rerouting. Without doing this,
|
||||
nothing will happen.
|
||||
|
||||
```language-php
|
||||
$conf['reroute_email_enable'] = TRUE;
|
||||
```
|
||||
|
||||
The next option is to whether to show rerouting description in mail body. I usually have this enabled. Set this to TRUE or FALSE depending on your preference.
|
||||
The next option is to whether to show rerouting description in mail body. I
|
||||
usually have this enabled. Set this to TRUE or FALSE depending on your
|
||||
preference.
|
||||
|
||||
```language-php
|
||||
$conf['reroute_email_enable_message'] = TRUE;
|
||||
```
|
||||
|
||||
The last setting is the email address to use. If you're entering a single address, you can add it as a simple string.
|
||||
The last setting is the email address to use. If you're entering a single
|
||||
address, you can add it as a simple string.
|
||||
|
||||
```language-php
|
||||
$conf['reroute_email_address'] = 'person1@example.com';
|
||||
```
|
||||
|
||||
In this example, all emails from the site will be rerouted to person1@example.com.
|
||||
In this example, all emails from the site will be rerouted to
|
||||
person1@example.com.
|
||||
|
||||
If you want to add multiple addresses, these should be added in a semicolon-delimited list. Whilst you could add these also as a string, I prefer to use an array of addresses and the `implode()` function.
|
||||
If you want to add multiple addresses, these should be added in a
|
||||
semicolon-delimited list. Whilst you could add these also as a string, I prefer
|
||||
to use an array of addresses and the `implode()` function.
|
||||
|
||||
```language-php
|
||||
$conf['reroute_email_address'] = implode(';', array(
|
||||
|
@ -46,4 +65,6 @@ $conf['reroute_email_address'] = implode(';', array(
|
|||
));
|
||||
```
|
||||
|
||||
In this example, person2@example.com and person3@example.com would receive their emails from the site as normal. Any emails to addresses not in the array would continue to be redirected to person1@example.com.
|
||||
In this example, person2@example.com and person3@example.com would receive their
|
||||
emails from the site as normal. Any emails to addresses not in the array would
|
||||
continue to be redirected to person1@example.com.
|
||||
|
|
|
@ -8,17 +8,29 @@ tags:
|
|||
- modules
|
||||
- patches
|
||||
---
|
||||
Earlier this year, I posted a solution to [an issue](http://drupal.org/node/753898) on the Drupal.org issue queue. Originally, I just posted the code back onto the issue, but have now created a patch that can easily be applied to any Drupal 6 installation. Here is a run-through of the process of creating and applying a patch. In this case, I made changes to the `user_pass_validate()` function that's found within `modules/user/user.pages.inc`.
|
||||
|
||||
To begin with, a download a fresh copy of Drupal 6.19 and created a copy of the original user.pages.inc file. Within the duplicate file, I made the same changes to the function that I did in earlier code, and saved the changes. Now, within my Terminal, I can navigate to Drupal's root directory and create the patch.
|
||||
Earlier this year, I posted a solution to
|
||||
[an issue](http://drupal.org/node/753898) on the Drupal.org issue queue.
|
||||
Originally, I just posted the code back onto the issue, but have now created a
|
||||
patch that can easily be applied to any Drupal 6 installation. Here is a
|
||||
run-through of the process of creating and applying a patch. In this case, I
|
||||
made changes to the `user_pass_validate()` function that's found within
|
||||
`modules/user/user.pages.inc`.
|
||||
|
||||
To begin with, a download a fresh copy of Drupal 6.19 and created a copy of the
|
||||
original user.pages.inc file. Within the duplicate file, I made the same changes
|
||||
to the function that I did in earlier code, and saved the changes. Now, within
|
||||
my Terminal, I can navigate to Drupal's root directory and create the patch.
|
||||
|
||||
```language-bash
|
||||
diff -rup modules/user/user.pages.inc modules/user/user.pages2.inc > /Users/oliver/Desktop/different_messages_for_blocked_users.patch
|
||||
```
|
||||
|
||||
This command compares the differences between the two files, and creates the specified patch file.
|
||||
This command compares the differences between the two files, and creates the
|
||||
specified patch file.
|
||||
|
||||
To apply the patch to my Drupal installation, I go back to Terminal and run the following code:
|
||||
To apply the patch to my Drupal installation, I go back to Terminal and run the
|
||||
following code:
|
||||
|
||||
```language-bash
|
||||
patch -p0 < /Users/oliver/Desktop/different_messages_for_blocked_users.patch
|
||||
|
@ -32,4 +44,7 @@ patch -p0 -R < /Users/oliver/Desktop/different_messages_for_blocked_users.patch
|
|||
|
||||
And that's it!
|
||||
|
||||
There is also a Git patch creation workflow, which is described at <http://groups.drupal.org/node/91424>. Thanks to [Randy Fay](http://randyfay.com) for making me aware of this, and suggesting a slight change to my original patch creation command.
|
||||
There is also a Git patch creation workflow, which is described at
|
||||
<http://groups.drupal.org/node/91424>. Thanks to
|
||||
[Randy Fay](http://randyfay.com) for making me aware of this, and suggesting a
|
||||
slight change to my original patch creation command.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
title: Create a Better Photo Gallery in Drupal - Part 1
|
||||
date: 2010-08-11
|
||||
excerpt: How I started converting and migrating a Coppermine photo gallery into Drupal.
|
||||
excerpt:
|
||||
How I started converting and migrating a Coppermine photo gallery into Drupal.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupal-6
|
||||
|
@ -13,27 +14,46 @@ tags:
|
|||
- views-attach
|
||||
- drupal
|
||||
---
|
||||
Recently, I converted a client's static HTML website, along with their Coppermine Photo Gallery, into a Drupal-powered website.
|
||||
|
||||
Over the next few posts, I'll be replicating the process that I used during the conversion, and how I added some additional features to my Drupal gallery.
|
||||
Recently, I converted a client's static HTML website, along with their
|
||||
Coppermine Photo Gallery, into a Drupal-powered website.
|
||||
|
||||
To begin with, I created my photo gallery as described by [Jeff Eaton](http://www.lullabot.com/about/team/jeff-eaton) in [this screencast](http://www.lullabot.com/articles/photo-galleries-views-attach), downloaded all my client's previous photos via FTP, and quickly added them into the new gallery using the [Imagefield Import](http://drupal.org/project/imagefield_import) module (which I mentioned [previously](/blog/quickly-import-multiples-images-using-imagefieldimport-module/)).
|
||||
Over the next few posts, I'll be replicating the process that I used during the
|
||||
conversion, and how I added some additional features to my Drupal gallery.
|
||||
|
||||
When I compare this to the previous gallery, I can see several differences which I'd like to include. The first of which is the number of photos in each gallery, and the date that the most recent photo was added.
|
||||
To begin with, I created my photo gallery as described by
|
||||
[Jeff Eaton](http://www.lullabot.com/about/team/jeff-eaton) in
|
||||
[this screencast](http://www.lullabot.com/articles/photo-galleries-views-attach),
|
||||
downloaded all my client's previous photos via FTP, and quickly added them into
|
||||
the new gallery using the
|
||||
[Imagefield Import](http://drupal.org/project/imagefield_import) module (which I
|
||||
mentioned
|
||||
[previously](/blog/quickly-import-multiples-images-using-imagefieldimport-module/)).
|
||||
|
||||
To do this, I'd need to query my website's database. To begin with, I wanted to have a list of all the galleries on my site which are published, and what they're unique node ID values are. To do this, I opened Sequel Pro and entered the following code:
|
||||
When I compare this to the previous gallery, I can see several differences which
|
||||
I'd like to include. The first of which is the number of photos in each gallery,
|
||||
and the date that the most recent photo was added.
|
||||
|
||||
To do this, I'd need to query my website's database. To begin with, I wanted to
|
||||
have a list of all the galleries on my site which are published, and what
|
||||
they're unique node ID values are. To do this, I opened Sequel Pro and entered
|
||||
the following code:
|
||||
|
||||
```language-sql
|
||||
SELECT title
|
||||
AS title, nid
|
||||
SELECT title
|
||||
AS title, nid
|
||||
AS gallery_idFROM node
|
||||
WHERE type = 'gallery'
|
||||
AND status = 1;
|
||||
```
|
||||
|
||||
As the nid value of each gallery corresponds with the 'field_gallery_nid' field within the content_type_photo field, I can now query the database and retrieve information about each specific gallery.
|
||||
As the nid value of each gallery corresponds with the 'field_gallery_nid' field
|
||||
within the content_type_photo field, I can now query the database and retrieve
|
||||
information about each specific gallery.
|
||||
|
||||
For example, using [aliasing](http://www.w3schools.com/sql/sql_alias.asp) within my SQL statement, I can retrieve a list of all the published photos within the 'British Squad 2008' gallery by using the following code:
|
||||
For example, using [aliasing](http://www.w3schools.com/sql/sql_alias.asp) within
|
||||
my SQL statement, I can retrieve a list of all the published photos within the
|
||||
'British Squad 2008' gallery by using the following code:
|
||||
|
||||
```language-sql
|
||||
SELECT n.title, n.nid, p.field_gallery_nid
|
||||
|
@ -43,7 +63,8 @@ AND n.status = 1
|
|||
AND n.nid = p.nid;
|
||||
```
|
||||
|
||||
I can easily change this to count the number of published nodes by changing the first line of the query to read SELECT COUNT(*).
|
||||
I can easily change this to count the number of published nodes by changing the
|
||||
first line of the query to read SELECT COUNT(\*).
|
||||
|
||||
```language-sql
|
||||
SELECT COUNT(*)
|
||||
|
@ -53,46 +74,55 @@ AND n.status = 1
|
|||
AND n.nid = p.nid;
|
||||
```
|
||||
|
||||
As I've used the [Views Attach](http://drupal.org/project/views_attach) module, and I'm embedding the photos directly into the Gallery nodes, I easily add this to each gallery by creating a custom node-gallery.tpl.php file within my theme. I can then use the following PHP code to retrieve the node ID for that specific gallery:
|
||||
As I've used the [Views Attach](http://drupal.org/project/views_attach) module,
|
||||
and I'm embedding the photos directly into the Gallery nodes, I easily add this
|
||||
to each gallery by creating a custom node-gallery.tpl.php file within my theme.
|
||||
I can then use the following PHP code to retrieve the node ID for that specific
|
||||
gallery:
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
$selected_gallery = db_result(db_query("
|
||||
SELECT nid
|
||||
FROM {node}
|
||||
WHERE type = 'gallery'
|
||||
SELECT nid
|
||||
FROM {node}
|
||||
WHERE type = 'gallery'
|
||||
AND title = '$title'
|
||||
"));
|
||||
?>
|
||||
```
|
||||
|
||||
I can then use this variable as part of my next query to count the number of photos within that gallery, similar to what I did earlier.
|
||||
I can then use this variable as part of my next query to count the number of
|
||||
photos within that gallery, similar to what I did earlier.
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
$gallery_total = db_result(db_query("
|
||||
SELECT COUNT(*)
|
||||
FROM {content_type_photo}
|
||||
SELECT COUNT(*)
|
||||
FROM {content_type_photo}
|
||||
WHERE field_gallery_nid = $selected_gallery
|
||||
"));
|
||||
?>
|
||||
```
|
||||
|
||||
Next, I wanted to display the date that the last photo was displayed within each album. This was done by using a similar query that also sorted the results in a descending order, and limited it to one result - effectively only returning the created date for the newest photo.
|
||||
Next, I wanted to display the date that the last photo was displayed within each
|
||||
album. This was done by using a similar query that also sorted the results in a
|
||||
descending order, and limited it to one result - effectively only returning the
|
||||
created date for the newest photo.
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
$latest_photo = db_result(db_query("
|
||||
SELECT n.created
|
||||
FROM {node} n, {content_type_photo} p
|
||||
WHERE p.field_gallery_nid = $selected_gallery
|
||||
AND n.nid = p.nid
|
||||
SELECT n.created
|
||||
FROM {node} n, {content_type_photo} p
|
||||
WHERE p.field_gallery_nid = $selected_gallery
|
||||
AND n.nid = p.nid
|
||||
ORDER BY n.created DESC LIMIT 1
|
||||
"));
|
||||
?>
|
||||
```
|
||||
|
||||
This was all then added into a 'print' statement which displayed it into the page.
|
||||
This was all then added into a 'print' statement which displayed it into the
|
||||
page.
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
|
@ -106,7 +136,9 @@ if ($selected_gallery_total != 0) {
|
|||
|
||||
OK, so let's take a look at the Gallery so far:
|
||||
|
||||
You will notice that the returned date value for the latest photo added is displaying the UNIX timestamp instead of in a more readable format. This can be changed by altering the 'print' statement to include a PHP 'date' function:
|
||||
You will notice that the returned date value for the latest photo added is
|
||||
displaying the UNIX timestamp instead of in a more readable format. This can be
|
||||
changed by altering the 'print' statement to include a PHP 'date' function:
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
|
@ -118,6 +150,12 @@ if ($selected_gallery_total != 0) {
|
|||
?>
|
||||
```
|
||||
|
||||
The values that I've entered are from [this page](http://php.net/manual/en/function.date.php) on PHP.net, and can be changed according on how you want the date to be displayed.
|
||||
The values that I've entered are from
|
||||
[this page](http://php.net/manual/en/function.date.php) on PHP.net, and can be
|
||||
changed according on how you want the date to be displayed.
|
||||
|
||||
As I've added all of these photos today, then the correct dates are being displayed. However, on the client's original website, the majority of these photos were pubished several months or years ago, and I'd like the new website to still reflect the original created dates. As opposed to modifying each individual photograph, I'll be doing this in bulk in my next post.
|
||||
As I've added all of these photos today, then the correct dates are being
|
||||
displayed. However, on the client's original website, the majority of these
|
||||
photos were pubished several months or years ago, and I'd like the new website
|
||||
to still reflect the original created dates. As opposed to modifying each
|
||||
individual photograph, I'll be doing this in bulk in my next post.
|
||||
|
|
|
@ -9,9 +9,15 @@ tags:
|
|||
- sql
|
||||
- sequel-pro
|
||||
---
|
||||
At the end of my last post, I'd finished creating the first part of the new photo gallery, but I wanted to change the dates of the published photos to reflect the ones on the client's original website.
|
||||
|
||||
Firstly, I'll refer to the previous list of published galleries that I created before, and create something different that also displays the created and modified dates. Picking the node ID of the required gallery, I used the following SQL query to display a list of photos.
|
||||
At the end of my last post, I'd finished creating the first part of the new
|
||||
photo gallery, but I wanted to change the dates of the published photos to
|
||||
reflect the ones on the client's original website.
|
||||
|
||||
Firstly, I'll refer to the previous list of published galleries that I created
|
||||
before, and create something different that also displays the created and
|
||||
modified dates. Picking the node ID of the required gallery, I used the
|
||||
following SQL query to display a list of photos.
|
||||
|
||||
```language-sql
|
||||
SELECT n.title, n.nid, n.created, n.changed, p.field_gallery_nid
|
||||
|
@ -20,9 +26,15 @@ AND p.field_gallery_nid = 103AND n.nid = p.nid
|
|||
ORDER BY n.nid ASC;
|
||||
```
|
||||
|
||||
When I look back at the old photo gallery, I can see that the previous 'last added' date was June 27, 2008. So, how do I update my new photos to reflect that date? Using <http://www.onlineconversion.com/unix_time.htm>, I can enter the required date in its readable format, and it will give me the equivilent UNIX timestamp. To keep things relatively simple, I'll set all photos within this gallery to the same time.
|
||||
When I look back at the old photo gallery, I can see that the previous 'last
|
||||
added' date was June 27, 2008. So, how do I update my new photos to reflect that
|
||||
date? Using <http://www.onlineconversion.com/unix_time.htm>, I can enter the
|
||||
required date in its readable format, and it will give me the equivilent UNIX
|
||||
timestamp. To keep things relatively simple, I'll set all photos within this
|
||||
gallery to the same time.
|
||||
|
||||
The result that I'm given is '1217149200'. I can now use an UPDATE statement within another SQL query to update the created and modified dates.
|
||||
The result that I'm given is '1217149200'. I can now use an UPDATE statement
|
||||
within another SQL query to update the created and modified dates.
|
||||
|
||||
```language-sql
|
||||
UPDATE node
|
||||
|
@ -34,8 +46,13 @@ SET
|
|||
WHERE content_type_photo.field_gallery_nid = 103
|
||||
```
|
||||
|
||||
Now when I query the database, both the created and modified dates have been updated, and when I return to the new photo gallery, the updated value is being displayed.
|
||||
Now when I query the database, both the created and modified dates have been
|
||||
updated, and when I return to the new photo gallery, the updated value is being
|
||||
displayed.
|
||||
|
||||
Once the changes have been applied, it's a case of repeating the above process for each of the required galleries.
|
||||
Once the changes have been applied, it's a case of repeating the above process
|
||||
for each of the required galleries.
|
||||
|
||||
In the next post, I'll explain how to add a count of published galleries and photos on the main photo gallery page, as well as how to install and configure the [Shadowbox](http://drupal.org/project/shadowbox) module.
|
||||
In the next post, I'll explain how to add a count of published galleries and
|
||||
photos on the main photo gallery page, as well as how to install and configure
|
||||
the [Shadowbox](http://drupal.org/project/shadowbox) module.
|
||||
|
|
|
@ -5,7 +5,14 @@ excerpt: The missing code to get totals of galleries and photos.
|
|||
tags:
|
||||
- drupal
|
||||
---
|
||||
Today, I realised that I hadn't published the code that I used to create the total figures of galleries and photos at the top of the gallery (I said at the end of [Part 2](/blog/create-better-photo-gallery-drupal-part-2/ "Create a Better Photo Gallery in Drupal - Part 2") that I'd include it in [Part 3](/blog/create-better-photo-gallery-drupal-part-3/ "Create a Better Photo Gallery in Drupal - Part 3"), but I forgot). So, here it is:
|
||||
|
||||
Today, I realised that I hadn't published the code that I used to create the
|
||||
total figures of galleries and photos at the top of the gallery (I said at the
|
||||
end of
|
||||
[Part 2](/blog/create-better-photo-gallery-drupal-part-2/ 'Create a Better Photo Gallery in Drupal - Part 2')
|
||||
that I'd include it in
|
||||
[Part 3](/blog/create-better-photo-gallery-drupal-part-3/ 'Create a Better Photo Gallery in Drupal - Part 3'),
|
||||
but I forgot). So, here it is:
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
|
@ -19,12 +26,12 @@ while($gallery = db_fetch_array($galleries)) {
|
|||
$gallery_id = $gallery['nid'];
|
||||
$photos = $photos + db_result(db_query("SELECT COUNT(*) FROM node n, content_type_photo ctp WHERE n.status = 1 AND n.type = 'photo' AND ctp.field_gallery_nid = $gallery_id AND n.nid = ctp.nid"));
|
||||
}
|
||||
|
||||
|
||||
// Prints the output.
|
||||
print 'There ';
|
||||
if($photos == 1) {
|
||||
print 'is';
|
||||
}
|
||||
}
|
||||
else {
|
||||
print 'are';
|
||||
}
|
||||
|
@ -32,20 +39,20 @@ print ' currently ';
|
|||
print $photos . ' ';
|
||||
if($photos == 1) {
|
||||
print 'photo';
|
||||
}
|
||||
}
|
||||
else {
|
||||
print 'photos';
|
||||
}
|
||||
}
|
||||
print ' in ';
|
||||
|
||||
|
||||
// Counts the number of published galleries on the site.
|
||||
$galleries = db_result(db_query("SELECT COUNT(*) FROM {node} WHERE TYPE = 'gallery' AND STATUS = 1"));
|
||||
|
||||
|
||||
// Prints the number of published galleries.
|
||||
print $galleries;
|
||||
if ($galleries == 1) {
|
||||
print ' gallery';
|
||||
}
|
||||
}
|
||||
else {
|
||||
print ' galleries';
|
||||
}
|
||||
|
@ -53,4 +60,5 @@ print '.';
|
|||
?>
|
||||
```
|
||||
|
||||
It was applied to the view as a header which had the input format set to PHP code.
|
||||
It was applied to the view as a header which had the input format set to PHP
|
||||
code.
|
||||
|
|
|
@ -5,23 +5,38 @@ excerpt: Grouping galleries by category.
|
|||
tags:
|
||||
- drupal
|
||||
---
|
||||
The next part of the new gallery that I want to implement is to group the galleries by their respective categories. The first step is to edit my original photo_gallery view and add an additional display.
|
||||
|
||||
I've called it 'Taxonomy', and it's similar to the original 'All Galleries' view. The differences are that I've added the taxonomy term as an argument, removed the header, and updated the path to be `gallery/%`. The other thing that I need to do is overwrite the output of the original 'All Galleries' View by creating a file called `views-view--photo-gallery--page-1.tpl.php` and placing it within my theme directory.
|
||||
The next part of the new gallery that I want to implement is to group the
|
||||
galleries by their respective categories. The first step is to edit my original
|
||||
photo_gallery view and add an additional display.
|
||||
|
||||
Within that file, I can remove the standard content output. This still outputs the heading information from the original View. I can now use the function called 'views_embed_view' to embed my taxonomy display onto the display. The views_embed_view function is as follows:
|
||||
I've called it 'Taxonomy', and it's similar to the original 'All Galleries'
|
||||
view. The differences are that I've added the taxonomy term as an argument,
|
||||
removed the header, and updated the path to be `gallery/%`. The other thing that
|
||||
I need to do is overwrite the output of the original 'All Galleries' View by
|
||||
creating a file called `views-view--photo-gallery--page-1.tpl.php` and placing
|
||||
it within my theme directory.
|
||||
|
||||
Within that file, I can remove the standard content output. This still outputs
|
||||
the heading information from the original View. I can now use the function
|
||||
called 'views_embed_view' to embed my taxonomy display onto the display. The
|
||||
views_embed_view function is as follows:
|
||||
|
||||
```language-php
|
||||
<?php views_embed_view('my_view', 'block_1', $arg1, $arg2); ?>
|
||||
```
|
||||
|
||||
So, to display the galleries that are assigned the taxonomy of 'tournaments', I can use the following:
|
||||
So, to display the galleries that are assigned the taxonomy of 'tournaments', I
|
||||
can use the following:
|
||||
|
||||
```language-php
|
||||
<?php print views_embed_view('photo_gallery', 'page_2', 'tournaments'); ?>
|
||||
```
|
||||
|
||||
To reduce the amount of code needed, I can use the following 'while' loop to generate the same code for each taxonomy term. It dynamically retrieves the relevant taxonomy terms from the database, and uses each name as the argument for the view.
|
||||
To reduce the amount of code needed, I can use the following 'while' loop to
|
||||
generate the same code for each taxonomy term. It dynamically retrieves the
|
||||
relevant taxonomy terms from the database, and uses each name as the argument
|
||||
for the view.
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
|
|
|
@ -10,14 +10,35 @@ tags:
|
|||
- nodequeue
|
||||
- oliverdavies.co.uk
|
||||
---
|
||||
I recently decided that I wanted to have a block displayed in a sidebar on my site containing icons and links to my social media profiles - [Twitter](http://twitter.com/opdavies), [Facebook](http://facebook.com/opdavies) etc. I tried the [Follow](http://drupal.org/project/follow) module, but it lacked the option to add extra networks such my [Drupal.org](http://drupal.org/user/381388) account, and my [RSS feed](http://oliverdavies.co.uk/rss.xml). I started to create my own version, and then found [this Blog post](http://www.hankpalan.com/blog/drupal-themes/add-your-social-connections-drupal-icons) by Hank Palan.
|
||||
|
||||
I created a 'Social icon' content type with the body field removed, and with fields for a link and image - then downloaded the favicons from the appropriate websites to use.
|
||||
I recently decided that I wanted to have a block displayed in a sidebar on my
|
||||
site containing icons and links to my social media profiles -
|
||||
[Twitter](http://twitter.com/opdavies), [Facebook](http://facebook.com/opdavies)
|
||||
etc. I tried the [Follow](http://drupal.org/project/follow) module, but it
|
||||
lacked the option to add extra networks such my
|
||||
[Drupal.org](http://drupal.org/user/381388) account, and my
|
||||
[RSS feed](http://oliverdavies.co.uk/rss.xml). I started to create my own
|
||||
version, and then found
|
||||
[this Blog post](http://www.hankpalan.com/blog/drupal-themes/add-your-social-connections-drupal-icons)
|
||||
by Hank Palan.
|
||||
|
||||
However, instead of using a custom template (node-custom.tpl.php) file, I used the Views module.
|
||||
I created a 'Social icon' content type with the body field removed, and with
|
||||
fields for a link and image - then downloaded the favicons from the appropriate
|
||||
websites to use.
|
||||
|
||||
I added fields for the node titles, and the link from the node's content. Both of these are excluded from being displayed on the site. I then re-wrote the output of the Icon field to create the link using the URL, and using the node's title as the image's alternative text and the link's title.
|
||||
However, instead of using a custom template (node-custom.tpl.php) file, I used
|
||||
the Views module.
|
||||
|
||||
I also used the [Nodequeue](http://drupal.org/project/nodequeue) module to create a nodequeue and arrange the icons in the order that I wanted them to be displayed. Once this was added as a relationship within my View, I was able to use node's position in the nodequeue as the sort criteria.
|
||||
I added fields for the node titles, and the link from the node's content. Both
|
||||
of these are excluded from being displayed on the site. I then re-wrote the
|
||||
output of the Icon field to create the link using the URL, and using the node's
|
||||
title as the image's alternative text and the link's title.
|
||||
|
||||
To complete the process, I used the [CSS Injector](http://drupal.org/project/css_injector) module to add some additional CSS styling to position and space out the icons.
|
||||
I also used the [Nodequeue](http://drupal.org/project/nodequeue) module to
|
||||
create a nodequeue and arrange the icons in the order that I wanted them to be
|
||||
displayed. Once this was added as a relationship within my View, I was able to
|
||||
use node's position in the nodequeue as the sort criteria.
|
||||
|
||||
To complete the process, I used the
|
||||
[CSS Injector](http://drupal.org/project/css_injector) module to add some
|
||||
additional CSS styling to position and space out the icons.
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
---
|
||||
title: Create a Flickr Photo Gallery Using Feeds, CCK and Views
|
||||
date: 2010-06-28
|
||||
excerpt: In this tutorial, I'll show you how to create a photo gallery which uses photos imported from Flickr.
|
||||
excerpt:
|
||||
In this tutorial, I'll show you how to create a photo gallery which uses
|
||||
photos imported from Flickr.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupal-6
|
||||
|
@ -14,33 +16,56 @@ tags:
|
|||
- flickr
|
||||
- imagefield
|
||||
---
|
||||
In this tutorial, I'll show you how to create a photo gallery which uses photos imported from [Flickr](http://www.flickr.com).
|
||||
|
||||
In this tutorial, I'll show you how to create a photo gallery which uses photos
|
||||
imported from [Flickr](http://www.flickr.com).
|
||||
|
||||
The modules that I'll use to create the Gallery are:
|
||||
|
||||
* [CCK](http://drupal.org/project/cck)
|
||||
* [Feeds](http://drupal.org/project/feeds)
|
||||
* [Feeds Image Grabber](http://drupal.org/project/feeds_imagegrabber)
|
||||
* [FileField](http://drupal.org/project/filefield)
|
||||
* [ImageAPI](http://drupal.org/project/imageapi)
|
||||
* [ImageCache](http://drupal.org/project/imagecache)
|
||||
* [ImageField](http://drupal.org/project/imagefield)
|
||||
* [Views](http://drupal.org/project/views)
|
||||
- [CCK](http://drupal.org/project/cck)
|
||||
- [Feeds](http://drupal.org/project/feeds)
|
||||
- [Feeds Image Grabber](http://drupal.org/project/feeds_imagegrabber)
|
||||
- [FileField](http://drupal.org/project/filefield)
|
||||
- [ImageAPI](http://drupal.org/project/imageapi)
|
||||
- [ImageCache](http://drupal.org/project/imagecache)
|
||||
- [ImageField](http://drupal.org/project/imagefield)
|
||||
- [Views](http://drupal.org/project/views)
|
||||
|
||||
The first thing that I did was to create a content type to store my imported images. I named it 'Photo', removed the Body field, and added an Image field.
|
||||
The first thing that I did was to create a content type to store my imported
|
||||
images. I named it 'Photo', removed the Body field, and added an Image field.
|
||||
|
||||
Next, I installed and configured the Feeds and Image Grabber module. I used an overridden default Feed to import my photos from Flickr using the following settings:
|
||||
Next, I installed and configured the Feeds and Image Grabber module. I used an
|
||||
overridden default Feed to import my photos from Flickr using the following
|
||||
settings:
|
||||
|
||||
* **Basic settings:** I changed the Refresh time to 15 minutes.
|
||||
* **Processor settings:** I changed the content type to 'Photo', and the author's name from 'anonymous'.
|
||||
* **Processor mapping:** I added a new mapping from 'Item URL (link)' to 'Photo (FIG)'. The Photo FIG target is added by the Image Grabber module.
|
||||
- **Basic settings:** I changed the Refresh time to 15 minutes.
|
||||
- **Processor settings:** I changed the content type to 'Photo', and the
|
||||
author's name from 'anonymous'.
|
||||
- **Processor mapping:** I added a new mapping from 'Item URL (link)' to 'Photo
|
||||
(FIG)'. The Photo FIG target is added by the Image Grabber module.
|
||||
|
||||
Next, I needed to create the actual Feed, which I did by clicking 'Import' within the Navigation menu, and clicking 'Feed'. I gave it a title, entered the URL to my RSS feed from Flickr, and enabled the Image Grabber for this feed.
|
||||
Next, I needed to create the actual Feed, which I did by clicking 'Import'
|
||||
within the Navigation menu, and clicking 'Feed'. I gave it a title, entered the
|
||||
URL to my RSS feed from Flickr, and enabled the Image Grabber for this feed.
|
||||
|
||||
Once the Feed is created, the latest 20 images from the RSS feed are imported and 20 new Photos nodes are created. In the example below, the image with the 'Photo' label is the Image field mapped by the Image Grabber module. It is this image that I'll be displaying within my Gallery.
|
||||
Once the Feed is created, the latest 20 images from the RSS feed are imported
|
||||
and 20 new Photos nodes are created. In the example below, the image with the
|
||||
'Photo' label is the Image field mapped by the Image Grabber module. It is this
|
||||
image that I'll be displaying within my Gallery.
|
||||
|
||||
With the new Photo nodes created, I then created the View to display them.
|
||||
|
||||
The View selects the image within the Photo content type, and displays in it a grid using an ImageCache preset. The View is limited to 20 nodes per page, and uses a full pager if this is exceeded. The nodes are sorted by the descending post date, and filtered by whether or not they are published, and only to include Photo nodes.
|
||||
The View selects the image within the Photo content type, and displays in it a
|
||||
grid using an ImageCache preset. The View is limited to 20 nodes per page, and
|
||||
uses a full pager if this is exceeded. The nodes are sorted by the descending
|
||||
post date, and filtered by whether or not they are published, and only to
|
||||
include Photo nodes.
|
||||
|
||||
As an additional effect, I also included the 'Feeds Item - Item Link' field, which is basically the original link from the RSS feed. By checking the box the exclude the item from the display, it is not shown, but makes the link available to be used elsewhere. By checking the box 'Re-write the output for this field' on the 'Content: Photo' field, I was able to add the replacement token (in this case, [url]) as the path for a link around each image. This meant that when someone clicked a thumbnail of a photo, they were directed to the Flickr website instead of the node within my Drupal site.
|
||||
As an additional effect, I also included the 'Feeds Item - Item Link' field,
|
||||
which is basically the original link from the RSS feed. By checking the box the
|
||||
exclude the item from the display, it is not shown, but makes the link available
|
||||
to be used elsewhere. By checking the box 'Re-write the output for this field'
|
||||
on the 'Content: Photo' field, I was able to add the replacement token (in this
|
||||
case, [url]) as the path for a link around each image. This meant that when
|
||||
someone clicked a thumbnail of a photo, they were directed to the Flickr website
|
||||
instead of the node within my Drupal site.
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
---
|
||||
title: Create Multigroups in Drupal 7 using Field Collections
|
||||
date: 2011-08-28
|
||||
excerpt: How to replicate CCK’s multigroups in Drupal 7 using the Field Collections module.
|
||||
excerpt:
|
||||
How to replicate CCK’s multigroups in Drupal 7 using the Field Collections
|
||||
module.
|
||||
tags:
|
||||
- drupal-7
|
||||
- drupal-planet
|
||||
|
@ -11,20 +13,47 @@ tags:
|
|||
- entity-api
|
||||
- multigroup
|
||||
---
|
||||
One of my favourite things lately in Drupal 6 has been CCK 3, and more specifically, the Content Multigroups sub-module. Basically this allows you to create a fieldset of various CCK fields, and then repeat that multiple times. For example, I use it on this site whist creating invoices for clients. I have a fieldset called 'Line Item', containing 'Description', 'Quantity' and 'Price' fields. With a standard fieldset, I could only have one instance of each field - however, using a multigroup, I can create multiple groups of line items which I then use within the invoice.
|
||||
|
||||
But at the time of writing this, there is no CCK 3 version for Drupal 7. So, I created the same thing using [Field Collection](http://drupal.org/project/field_collection) and [Entity](http://drupal.org/project/entity) modules.
|
||||
One of my favourite things lately in Drupal 6 has been CCK 3, and more
|
||||
specifically, the Content Multigroups sub-module. Basically this allows you to
|
||||
create a fieldset of various CCK fields, and then repeat that multiple times.
|
||||
For example, I use it on this site whist creating invoices for clients. I have a
|
||||
fieldset called 'Line Item', containing 'Description', 'Quantity' and 'Price'
|
||||
fields. With a standard fieldset, I could only have one instance of each field -
|
||||
however, using a multigroup, I can create multiple groups of line items which I
|
||||
then use within the invoice.
|
||||
|
||||
With the modules uploaded and enabled, go to admin/structure/field-collections and create a field collection.
|
||||
But at the time of writing this, there is no CCK 3 version for Drupal 7. So, I
|
||||
created the same thing using
|
||||
[Field Collection](http://drupal.org/project/field_collection) and
|
||||
[Entity](http://drupal.org/project/entity) modules.
|
||||
|
||||
With the module enabled, you can go to your content type and add a Field Collection field. By default, the only available Widget type is 'Hidden'.
|
||||
With the modules uploaded and enabled, go to admin/structure/field-collections
|
||||
and create a field collection.
|
||||
|
||||
Next, go to admin/structure/field-collections and add some fields to the field collection - the same way that you would for a content type. For this collection is going to contain two node reference fields - Image and Link.
|
||||
With the module enabled, you can go to your content type and add a Field
|
||||
Collection field. By default, the only available Widget type is 'Hidden'.
|
||||
|
||||
With the Field Collection created, I can now add it as a field within my content type.
|
||||
Next, go to admin/structure/field-collections and add some fields to the field
|
||||
collection - the same way that you would for a content type. For this collection
|
||||
is going to contain two node reference fields - Image and Link.
|
||||
|
||||
Whilst this works perfectly, the field collection is not editable from the node edit form. You need to load the node, and the collection is displayed here with add, edit, and delete buttons. This wasn't an ideal solution, and I wanted to be able to edit the fields within the collection from the node edit form - the same way as I can using multigroups in Drupal 6.
|
||||
With the Field Collection created, I can now add it as a field within my content
|
||||
type.
|
||||
|
||||
After some searching I found [a link to a patch](http://drupal.org/node/977890#comment-4184524) which when applied adds a 'subform' widget type to the field collection field and allows for it to be embedded into, and editable from within the node form. Going back to the content type fields page, and clicking on 'Hidden' (the name of the current widget), I can change it to subform and save my changes.
|
||||
Whilst this works perfectly, the field collection is not editable from the node
|
||||
edit form. You need to load the node, and the collection is displayed here with
|
||||
add, edit, and delete buttons. This wasn't an ideal solution, and I wanted to be
|
||||
able to edit the fields within the collection from the node edit form - the same
|
||||
way as I can using multigroups in Drupal 6.
|
||||
|
||||
With this change applied, when I go back to add or edit a node within this content type, my field collection will be easily editable directly within the form.
|
||||
After some searching I found
|
||||
[a link to a patch](http://drupal.org/node/977890#comment-4184524) which when
|
||||
applied adds a 'subform' widget type to the field collection field and allows
|
||||
for it to be embedded into, and editable from within the node form. Going back
|
||||
to the content type fields page, and clicking on 'Hidden' (the name of the
|
||||
current widget), I can change it to subform and save my changes.
|
||||
|
||||
With this change applied, when I go back to add or edit a node within this
|
||||
content type, my field collection will be easily editable directly within the
|
||||
form.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
---
|
||||
title: Create an Omega Subtheme with LESS CSS Preprocessor using Omega Tools and Drush
|
||||
title:
|
||||
Create an Omega Subtheme with LESS CSS Preprocessor using Omega Tools and
|
||||
Drush
|
||||
date: 2012-04-16
|
||||
excerpt: How to create an Omega subtheme on the command line using Drush.
|
||||
tags:
|
||||
|
@ -10,33 +12,53 @@ tags:
|
|||
- drupal-planet
|
||||
- drupal
|
||||
---
|
||||
In this tutorial I'll be showing how to create an [Omega](http://drupal.org/project/omega) subtheme using the [Omega Tools](http://drupal.org/project/omega_tools) module, and have it working with the [LESS CSS preprocessor](http://lesscss.org).
|
||||
|
||||
The first thing that I need to do is download the Omega theme and the Omega Tools and [LESS](http://drupal.org/project/less "LESS module on drupal.org") modules, and then to enable both modules. I'm doing this using Drush, but you can of course do this via the admin interface at admin/modules.
|
||||
In this tutorial I'll be showing how to create an
|
||||
[Omega](http://drupal.org/project/omega) subtheme using the
|
||||
[Omega Tools](http://drupal.org/project/omega_tools) module, and have it working
|
||||
with the [LESS CSS preprocessor](http://lesscss.org).
|
||||
|
||||
The first thing that I need to do is download the Omega theme and the Omega
|
||||
Tools and [LESS](http://drupal.org/project/less 'LESS module on drupal.org')
|
||||
modules, and then to enable both modules. I'm doing this using Drush, but you
|
||||
can of course do this via the admin interface at admin/modules.
|
||||
|
||||
```language-bash
|
||||
$ drush dl less omega omega_tools;
|
||||
$ drush en -y less omega_tools
|
||||
```
|
||||
|
||||
With the Omega Tools module enabled I get the drush omega-subtheme command that creates my Omega subtheme programatically. Using this command, I'm creating a new subtheme, enabling it and setting it as the default theme on my site.
|
||||
With the Omega Tools module enabled I get the drush omega-subtheme command that
|
||||
creates my Omega subtheme programatically. Using this command, I'm creating a
|
||||
new subtheme, enabling it and setting it as the default theme on my site.
|
||||
|
||||
```language-bash
|
||||
$ drush omega-subtheme "Oliver Davies" --machine_name="oliverdavies" --enable --set-default
|
||||
```
|
||||
|
||||
By default, four stylesheets are created within the subtheme's css directory. The first thing that I'm going to do is rename `global.css` to `global.less`.
|
||||
By default, four stylesheets are created within the subtheme's css directory.
|
||||
The first thing that I'm going to do is rename `global.css` to `global.less`.
|
||||
|
||||
```language-bash
|
||||
$ mv css/global.css css/global.less
|
||||
```
|
||||
|
||||
Now I need to find all references to global.css within my oliverdavies.info file. I did this using `$ nano oliverdavies.info`, pressing `Ctrl+W` to search, then `Ctrl+R` to replace, entering `global.css` as the search phrase, and then `global.less` as the replacement text. After making any changes to oliverdavies.info, I need to clear Drupal's caches for the changes to be applied.
|
||||
Now I need to find all references to global.css within my oliverdavies.info
|
||||
file. I did this using `$ nano oliverdavies.info`, pressing `Ctrl+W` to search,
|
||||
then `Ctrl+R` to replace, entering `global.css` as the search phrase, and then
|
||||
`global.less` as the replacement text. After making any changes to
|
||||
oliverdavies.info, I need to clear Drupal's caches for the changes to be
|
||||
applied.
|
||||
|
||||
```language-bash
|
||||
$ drush cc all
|
||||
```
|
||||
|
||||
I tested my changes by making some quick additions to my global.less file and reloading the page.
|
||||
I tested my changes by making some quick additions to my global.less file and
|
||||
reloading the page.
|
||||
|
||||
If your changes aren't applied, then confirm that your global.less file is enabled within your theme's configuration. I did this by going to admin/appearance/settings/oliverdavies, clicking on the Toggle styles tab within *Layout configuration* and finding global.less at the bottom of *Enable optional stylesheets*.
|
||||
If your changes aren't applied, then confirm that your global.less file is
|
||||
enabled within your theme's configuration. I did this by going to
|
||||
admin/appearance/settings/oliverdavies, clicking on the Toggle styles tab within
|
||||
_Layout configuration_ and finding global.less at the bottom of _Enable optional
|
||||
stylesheets_.
|
||||
|
|
|
@ -9,19 +9,42 @@ tags:
|
|||
- fancy-slide
|
||||
- slideshow
|
||||
---
|
||||
Whilst updating my About page, I thought about creating a slideshow of several images instead of just the one static image. When I looking on Drupal.org, the only slideshow modules were to create slideshows of images that were attached to different nodes - not multiple images attached to one node. Then, I found the [Fancy Slide](http://drupal.org/project/fancy_slide) module. It's a jQuery Slideshow module with features that include integration with the [CCK](http://drupal.org/project/cck), [ImageCache](http://drupal.org/project/imagecache) and [Nodequeue](http://drupal.org/project/nodequeue) modules.
|
||||
|
||||
I added an CCK Image field to my Page content type, and set the number of values to 3, then uploaded my images to the Page.
|
||||
Whilst updating my About page, I thought about creating a slideshow of several
|
||||
images instead of just the one static image. When I looking on Drupal.org, the
|
||||
only slideshow modules were to create slideshows of images that were attached to
|
||||
different nodes - not multiple images attached to one node. Then, I found the
|
||||
[Fancy Slide](http://drupal.org/project/fancy_slide) module. It's a jQuery
|
||||
Slideshow module with features that include integration with the
|
||||
[CCK](http://drupal.org/project/cck),
|
||||
[ImageCache](http://drupal.org/project/imagecache) and
|
||||
[Nodequeue](http://drupal.org/project/nodequeue) modules.
|
||||
|
||||
Whilst updating my About page, I thought about creating a slideshow of several images instead of just the one static image. When I looking on Drupal.org, the only slideshow modules were to create slideshows of images that were attached to different nodes - not multiple images attached to one node. Then, I found the [Fancy Slide](http://drupal.org/project/fancy_slide) module. It's a jQuery Slideshow module with features that include integration with the [CCK](http://drupal.org/project/cck), [ImageCache](http://drupal.org/project/imagecache) and [Nodequeue](http://drupal.org/project/nodequeue) modules.
|
||||
Once the Images were added, I went to the Fancy Slide settings page and created the slideshow.
|
||||
I added an CCK Image field to my Page content type, and set the number of values
|
||||
to 3, then uploaded my images to the Page.
|
||||
|
||||
I added the dimensions of my images, the type of animation, specified the node that contained the images, the slideshow field, delay between slides and transition speed. With the slideshow created, it now needed embedding into the page.
|
||||
Whilst updating my About page, I thought about creating a slideshow of several
|
||||
images instead of just the one static image. When I looking on Drupal.org, the
|
||||
only slideshow modules were to create slideshows of images that were attached to
|
||||
different nodes - not multiple images attached to one node. Then, I found the
|
||||
[Fancy Slide](http://drupal.org/project/fancy_slide) module. It's a jQuery
|
||||
Slideshow module with features that include integration with the
|
||||
[CCK](http://drupal.org/project/cck),
|
||||
[ImageCache](http://drupal.org/project/imagecache) and
|
||||
[Nodequeue](http://drupal.org/project/nodequeue) modules. Once the Images were
|
||||
added, I went to the Fancy Slide settings page and created the slideshow.
|
||||
|
||||
I added the following code into my About page, as described in the Fancy Slide readme.txt file - the number representing the ID of the slideshow.
|
||||
I added the dimensions of my images, the type of animation, specified the node
|
||||
that contained the images, the slideshow field, delay between slides and
|
||||
transition speed. With the slideshow created, it now needed embedding into the
|
||||
page.
|
||||
|
||||
I added the following code into my About page, as described in the Fancy Slide
|
||||
readme.txt file - the number representing the ID of the slideshow.
|
||||
|
||||
```language-php
|
||||
<?php print theme('fancy_slide', 1); ?>
|
||||
```
|
||||
|
||||
In my opinion, this adds a nice effect to the About page. I like it because it's easy to set up, and easy to add additional images later on if required.
|
||||
In my opinion, this adds a nice effect to the About page. I like it because it's
|
||||
easy to set up, and easy to add additional images later on if required.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
title: Create Virtual Hosts on Mac OS X Using VirtualHostX
|
||||
date: 2010-07-02
|
||||
excerpt: How to use the VirtualHostX application to manage virtual hosts on Mac OS X.
|
||||
excerpt:
|
||||
How to use the VirtualHostX application to manage virtual hosts on Mac OS X.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupal-6
|
||||
|
@ -9,16 +10,41 @@ tags:
|
|||
- virtual-hosts
|
||||
- virtualhostx
|
||||
---
|
||||
This isn't a Drupal related topic per se, but it is a walk-through of one of the applications that I use whilst doing Drupal development work. I assume, like most Mac OS X users, I use [MAMP](http://www.mamp.info/en/index.html) to run Apache, MySQL and PHP locally whilst developing. I also use virtual hosts in Apache to create local .dev domains which are as close as possible to the actual live domains. For example, if I was developing a site called mysite.com, my local development version would be mysite.dev.
|
||||
|
||||
Normally, I would have to edit the hosts file and Apache's httpd.conf file to create a virtual host. The first to set the domain and it's associated IP address, and the other to configure the domain's directory, default index file etc. However, using [VirtualHostX](http://clickontyler.com/virtualhostx), I can quickly create a virtual host without having to edt any files. Enter the virtual domain name, the local path and the port, and apply the settings. VirtualHostX automatically restarts Apache, so the domain is ready to work straight away. You can also enter custom directives from within the GUI.
|
||||
This isn't a Drupal related topic per se, but it is a walk-through of one of the
|
||||
applications that I use whilst doing Drupal development work. I assume, like
|
||||
most Mac OS X users, I use [MAMP](http://www.mamp.info/en/index.html) to run
|
||||
Apache, MySQL and PHP locally whilst developing. I also use virtual hosts in
|
||||
Apache to create local .dev domains which are as close as possible to the actual
|
||||
live domains. For example, if I was developing a site called mysite.com, my
|
||||
local development version would be mysite.dev.
|
||||
|
||||
There's also an option to share the host over the local network. Next, I intend on configuring a virtual Windows PC within VMware Fusion to view these domains so that I can do cross-browser testing before putting a site live.
|
||||
Normally, I would have to edit the hosts file and Apache's httpd.conf file to
|
||||
create a virtual host. The first to set the domain and it's associated IP
|
||||
address, and the other to configure the domain's directory, default index file
|
||||
etc. However, using [VirtualHostX](http://clickontyler.com/virtualhostx), I can
|
||||
quickly create a virtual host without having to edt any files. Enter the virtual
|
||||
domain name, the local path and the port, and apply the settings. VirtualHostX
|
||||
automatically restarts Apache, so the domain is ready to work straight away. You
|
||||
can also enter custom directives from within the GUI.
|
||||
|
||||
I ensured that my Apache configuration within MAMP was set to port 80, and that VirtualHostX was using Apache from MAMP instead of Apple's built-in Apache.
|
||||
There's also an option to share the host over the local network. Next, I intend
|
||||
on configuring a virtual Windows PC within VMware Fusion to view these domains
|
||||
so that I can do cross-browser testing before putting a site live.
|
||||
|
||||
**Note:** One problem that I had after setting this up, was that I was receving an error when attempting to open a Drupal website which said *'No such file or directory'.*
|
||||
I ensured that my Apache configuration within MAMP was set to port 80, and that
|
||||
VirtualHostX was using Apache from MAMP instead of Apple's built-in Apache.
|
||||
|
||||
After some troubleshooting, I found out that Web Sharing on my Mac had become enabled (I don't know why, I've never enabled it), and that this was causing a conflict with Apache. Once I opened my System Preferences and disabled it, everything worked fine!
|
||||
**Note:** One problem that I had after setting this up, was that I was receving
|
||||
an error when attempting to open a Drupal website which said _'No such file or
|
||||
directory'._
|
||||
|
||||
This, along with [MAMP](http://www.mamp.info/en/index.html), [Coda](http://www.panic.com/coda), [Sequel Pro](http://www.sequelpro.com), and [Transmit](http://www.panic.com/transmit), has become an essential tool within my development environment.
|
||||
After some troubleshooting, I found out that Web Sharing on my Mac had become
|
||||
enabled (I don't know why, I've never enabled it), and that this was causing a
|
||||
conflict with Apache. Once I opened my System Preferences and disabled it,
|
||||
everything worked fine!
|
||||
|
||||
This, along with [MAMP](http://www.mamp.info/en/index.html),
|
||||
[Coda](http://www.panic.com/coda), [Sequel Pro](http://www.sequelpro.com), and
|
||||
[Transmit](http://www.panic.com/transmit), has become an essential tool within
|
||||
my development environment.
|
||||
|
|
|
@ -9,9 +9,12 @@ tags:
|
|||
- zen
|
||||
- theming
|
||||
---
|
||||
How to use [Drush](https://drupal.org/project/drush) to quickly build a new sub-theme of [Zen](https://drupal.org/project/zen).
|
||||
|
||||
First, download the [Zen](https://drupal.org/project/zen "The Zen theme") theme if you haven't already done so.
|
||||
How to use [Drush](https://drupal.org/project/drush) to quickly build a new
|
||||
sub-theme of [Zen](https://drupal.org/project/zen).
|
||||
|
||||
First, download the [Zen](https://drupal.org/project/zen 'The Zen theme') theme
|
||||
if you haven't already done so.
|
||||
|
||||
```language-bash
|
||||
$ drush dl zen
|
||||
|
@ -28,8 +31,10 @@ The parameters that I'm passing it are:
|
|||
1. The human-readable name of the theme.
|
||||
2. The machine-readable name of the theme.
|
||||
3. The description of the theme (optional).
|
||||
4. A flag telling Drush not to include any right-to-left elements within my sub-theme as these aren't needed (optional).
|
||||
4. A flag telling Drush not to include any right-to-left elements within my
|
||||
sub-theme as these aren't needed (optional).
|
||||
|
||||
This will create a new theme in sites/all/themes/oliverdavies.
|
||||
|
||||
For further help, type `$ drush help zen` to see the Drush help page for the zen command.
|
||||
For further help, type `$ drush help zen` to see the Drush help page for the zen
|
||||
command.
|
||||
|
|
|
@ -1,31 +1,44 @@
|
|||
---
|
||||
title: Creating and using custom tokens in Drupal 7
|
||||
date: 2013-02-16
|
||||
excerpt: This post outlines the steps required to create your own custom tokens in Drupal.
|
||||
excerpt:
|
||||
This post outlines the steps required to create your own custom tokens in
|
||||
Drupal.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- drupal-7
|
||||
- tokens
|
||||
---
|
||||
This post outlines the steps required to create your own custom tokens in Drupal.
|
||||
|
||||
When writing the recent releases of the [Copyright Block](http://drupal.org/project/copyright_block) module, I used tokens to allow the user to edit and customise their copyright message and place the copyright_message:dates token in the desired position. When the block is rendered, the token is replaced by the necessary dates.
|
||||
This post outlines the steps required to create your own custom tokens in
|
||||
Drupal.
|
||||
|
||||
We will be using the fictional *foo* module to demonstrate this.
|
||||
When writing the recent releases of the
|
||||
[Copyright Block](http://drupal.org/project/copyright_block) module, I used
|
||||
tokens to allow the user to edit and customise their copyright message and place
|
||||
the copyright_message:dates token in the desired position. When the block is
|
||||
rendered, the token is replaced by the necessary dates.
|
||||
|
||||
We will be using the fictional _foo_ module to demonstrate this.
|
||||
|
||||
## Requirements
|
||||
|
||||
* [Token module](http://drupal.org/project/token)
|
||||
- [Token module](http://drupal.org/project/token)
|
||||
|
||||
## Recommended
|
||||
|
||||
* [Devel module](http://drupal.org/project/devel) - useful to run `dpm()` and `kpr()` functions
|
||||
* [Copyright Block module](http://drupal.org/project/copyright_block) - 7.x-2.x and 6.x-1.x use tokens, handy as a reference
|
||||
- [Devel module](http://drupal.org/project/devel) - useful to run `dpm()` and
|
||||
`kpr()` functions
|
||||
- [Copyright Block module](http://drupal.org/project/copyright_block) - 7.x-2.x
|
||||
and 6.x-1.x use tokens, handy as a reference
|
||||
|
||||
## Implementing hook_token_info()
|
||||
|
||||
The first thing that we need to do is define the new token type and/or the token itself, along with it's descriptive text. To view the existing tokens and types, use `dpm(token_get_info());`, assuming that you have the [Devel module](http://drupal.org/project/devel) installed.
|
||||
The first thing that we need to do is define the new token type and/or the token
|
||||
itself, along with it's descriptive text. To view the existing tokens and types,
|
||||
use `dpm(token_get_info());`, assuming that you have the
|
||||
[Devel module](http://drupal.org/project/devel) installed.
|
||||
|
||||
```language-php
|
||||
/**
|
||||
|
@ -42,13 +55,16 @@ function foo_token_info() {
|
|||
}
|
||||
```
|
||||
|
||||
In this case, the token called *bar* resides within the *foo* group.
|
||||
In this case, the token called _bar_ resides within the _foo_ group.
|
||||
|
||||
If I needed to add a new token within an existing token type, such as 'node', the syntax would be `$info['tokens']['node']['bar']`.
|
||||
If I needed to add a new token within an existing token type, such as 'node',
|
||||
the syntax would be `$info['tokens']['node']['bar']`.
|
||||
|
||||
## Implementing hook_tokens()
|
||||
|
||||
Now that the Token module is aware of our new token, we now need to determine what the token is replaced with. This is done using `hook_tokens()`. Here is the basic code needed for an implementation:
|
||||
Now that the Token module is aware of our new token, we now need to determine
|
||||
what the token is replaced with. This is done using `hook_tokens()`. Here is the
|
||||
basic code needed for an implementation:
|
||||
|
||||
```language-php
|
||||
/**
|
||||
|
@ -64,7 +80,13 @@ function foo_tokens($type, $tokens, array $data = array(), array $options = arra
|
|||
}
|
||||
```
|
||||
|
||||
The first thing to check for is the type of token using an `if()` function, as this could be an existing type like 'node', 'user' or 'site', or a custom token type like 'foo'. Once we're sure that we're looking at the right type(s), we can use `foreach ($tokens as $name => $original)` to loop through each of the available tokens using a `switch()`. For each token, you can perform some logic to work out the replacement text and then add it into the replacements array using `$replacements[$original] = $new;`.
|
||||
The first thing to check for is the type of token using an `if()` function, as
|
||||
this could be an existing type like 'node', 'user' or 'site', or a custom token
|
||||
type like 'foo'. Once we're sure that we're looking at the right type(s), we can
|
||||
use `foreach ($tokens as $name => $original)` to loop through each of the
|
||||
available tokens using a `switch()`. For each token, you can perform some logic
|
||||
to work out the replacement text and then add it into the replacements array
|
||||
using `$replacements[$original] = $new;`.
|
||||
|
||||
```language-php
|
||||
/**
|
||||
|
@ -127,7 +149,9 @@ function copyright_block_tokens($type, $tokens, array $data = array(), array $op
|
|||
|
||||
## Using token_replace()
|
||||
|
||||
With everything defined, all that we now need to do is pass some text through the `token_replace()` function to replace it with the values defined within `hook_token()`.
|
||||
With everything defined, all that we now need to do is pass some text through
|
||||
the `token_replace()` function to replace it with the values defined within
|
||||
`hook_token()`.
|
||||
|
||||
```language-php
|
||||
$a = t('Something');
|
||||
|
|
|
@ -1,30 +1,43 @@
|
|||
---
|
||||
title: Creating a Custom PHPUnit Command for Docksal
|
||||
date: 2018-05-06
|
||||
excerpt: How to write custom commands for Docksal, including one to easily run PHPUnit tests in Drupal 8.
|
||||
excerpt:
|
||||
How to write custom commands for Docksal, including one to easily run PHPUnit
|
||||
tests in Drupal 8.
|
||||
tags:
|
||||
- docksal
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-planet
|
||||
- phpunit
|
||||
- testing
|
||||
- docksal
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-planet
|
||||
- phpunit
|
||||
- testing
|
||||
---
|
||||
This week I’ve started writing some custom commands for my Drupal projects that use Docksal, including one to easily run PHPUnit tests in Drupal 8. This is the process of how I created this command.
|
||||
|
||||
This week I’ve started writing some custom commands for my Drupal projects that
|
||||
use Docksal, including one to easily run PHPUnit tests in Drupal 8. This is the
|
||||
process of how I created this command.
|
||||
|
||||
## What is Docksal?
|
||||
|
||||
Docksal is a local Docker-based development environment for Drupal projects and other frameworks and CMSes. It is our standard tool for local environments for projects at [Microserve][0].
|
||||
Docksal is a local Docker-based development environment for Drupal projects and
|
||||
other frameworks and CMSes. It is our standard tool for local environments for
|
||||
projects at [Microserve][0].
|
||||
|
||||
There was a [great talk][1] recently at Drupaldelphia about Docksal.
|
||||
|
||||
## Why write a custom command?
|
||||
|
||||
One of the things that Docksal offers (and is covered in the talk) is the ability to add custom commands to the Docksal’s `fin` CLI, either globally or as part of your project.
|
||||
One of the things that Docksal offers (and is covered in the talk) is the
|
||||
ability to add custom commands to the Docksal’s `fin` CLI, either globally or as
|
||||
part of your project.
|
||||
|
||||
As an advocate of automated testing and TDD practitioner, I write a lot of tests and run PHPUnit numerous times a day. I’ve also given [talks][6] and have [written other posts][7] on this site relating to testing in Drupal.
|
||||
As an advocate of automated testing and TDD practitioner, I write a lot of tests
|
||||
and run PHPUnit numerous times a day. I’ve also given [talks][6] and have
|
||||
[written other posts][7] on this site relating to testing in Drupal.
|
||||
|
||||
There are a couple of ways to run PHPUnit with Docksal. The first is to use `fin bash` to open a shell into the container, move into the docroot directory if needed, and run the `phpunit` command.
|
||||
There are a couple of ways to run PHPUnit with Docksal. The first is to use
|
||||
`fin bash` to open a shell into the container, move into the docroot directory
|
||||
if needed, and run the `phpunit` command.
|
||||
|
||||
```bash
|
||||
fin bash
|
||||
|
@ -39,44 +52,57 @@ cd docroot
|
|||
fin exec '../vendor/bin/phpunit -c core modules/custom'
|
||||
```
|
||||
|
||||
Both of these options require multiple steps as we need to be in the `docroot` directory where the Drupal code is located before the command can be run, and both have quite long commands to run PHPUnit itself - some of which is repeated every time.
|
||||
Both of these options require multiple steps as we need to be in the `docroot`
|
||||
directory where the Drupal code is located before the command can be run, and
|
||||
both have quite long commands to run PHPUnit itself - some of which is repeated
|
||||
every time.
|
||||
|
||||
By adding a custom command, I intend to:
|
||||
|
||||
1. Make it easier to get set up to run PHPUnit tests - i.e. setting up a `phpunit.xml` file.
|
||||
1. Make it easier to run the tests that we’d written by shortening the command and making it so it can be run anywhere within our project.
|
||||
1. Make it easier to get set up to run PHPUnit tests - i.e. setting up a
|
||||
`phpunit.xml` file.
|
||||
1. Make it easier to run the tests that we’d written by shortening the command
|
||||
and making it so it can be run anywhere within our project.
|
||||
|
||||
I also hoped to make it project agnostic so that I could add it onto any project and immediately run it.
|
||||
I also hoped to make it project agnostic so that I could add it onto any project
|
||||
and immediately run it.
|
||||
|
||||
## Creating the command
|
||||
|
||||
Each command is a file located within the `.docksal/commands` directory. The filename is the name of the command (e.g. `phpunit`) with no file extension.
|
||||
Each command is a file located within the `.docksal/commands` directory. The
|
||||
filename is the name of the command (e.g. `phpunit`) with no file extension.
|
||||
|
||||
To create the file, run this from the same directory where your `.docksal` directory is:
|
||||
To create the file, run this from the same directory where your `.docksal`
|
||||
directory is:
|
||||
|
||||
```bash
|
||||
mkdir -p .docksal/commands
|
||||
touch .docksal/commands/phpunit
|
||||
```
|
||||
|
||||
This will create a new, empty `.docksal/commands/phpunit` file, and now the `phpunit` command is now listed under "Custom commands" when we run `fin`.
|
||||
This will create a new, empty `.docksal/commands/phpunit` file, and now the
|
||||
`phpunit` command is now listed under "Custom commands" when we run `fin`.
|
||||
|
||||
![](/images/blog/docksal-phpunit-command/1.gif)
|
||||
|
||||
You can write commands with any interpreter. I’m going to use bash, so I’ll add the shebang to the top of the file.
|
||||
You can write commands with any interpreter. I’m going to use bash, so I’ll add
|
||||
the shebang to the top of the file.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
```
|
||||
|
||||
With this in place, I can now run `fin phpunit`, though there is no output displayed or actions performed as the rest of the file is empty.
|
||||
With this in place, I can now run `fin phpunit`, though there is no output
|
||||
displayed or actions performed as the rest of the file is empty.
|
||||
|
||||
## Adding a description and help text
|
||||
|
||||
Currently the description for our command when we run `fin` is the default "No description" text. I’d like to add something more relevant, so I’ll start by adding a new description.
|
||||
Currently the description for our command when we run `fin` is the default "No
|
||||
description" text. I’d like to add something more relevant, so I’ll start by
|
||||
adding a new description.
|
||||
|
||||
|
||||
fin interprets lines starting with `##` as documentation - the first of which it uses as the description.
|
||||
fin interprets lines starting with `##` as documentation - the first of which it
|
||||
uses as the description.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
@ -88,7 +114,9 @@ Now when I run it, I see the new description.
|
|||
|
||||
![](/images/blog/docksal-phpunit-command/2.gif)
|
||||
|
||||
Any additional lines are used as help text with running `fin help phpunit`. Here I’ll add an example command to demonstrate how to run it as well as some more in-depth text about what the command will do.
|
||||
Any additional lines are used as help text with running `fin help phpunit`. Here
|
||||
I’ll add an example command to demonstrate how to run it as well as some more
|
||||
in-depth text about what the command will do.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
@ -109,7 +137,9 @@ Now when I run `fin help phpunit`, I see the new help text.
|
|||
|
||||
### Setting the target
|
||||
|
||||
As I want the commands to be run within Docksal’s "cli" container, I can specify that with `exec_target`. If one isn’t specified, the commands are run locally on the host machine.
|
||||
As I want the commands to be run within Docksal’s "cli" container, I can specify
|
||||
that with `exec_target`. If one isn’t specified, the commands are run locally on
|
||||
the host machine.
|
||||
|
||||
```
|
||||
#: exec_target = cli
|
||||
|
@ -117,11 +147,13 @@ As I want the commands to be run within Docksal’s "cli" container, I can speci
|
|||
|
||||
### Available variables
|
||||
|
||||
These variables are provided by fin and are available to use within any custom commands:
|
||||
These variables are provided by fin and are available to use within any custom
|
||||
commands:
|
||||
|
||||
- `PROJECT_ROOT` - The absolute path to the nearest `.docksal` directory.
|
||||
- `DOCROOT` - name of the docroot folder.
|
||||
- `VIRTUAL_HOST` - the virtual host name for the project. Such as `myproject.docksal`.
|
||||
- `VIRTUAL_HOST` - the virtual host name for the project. Such as
|
||||
`myproject.docksal`.
|
||||
- `DOCKER_RUNNING` - (string) "true" or "false".
|
||||
|
||||
<div class="note" markdown="1">
|
||||
|
@ -135,17 +167,28 @@ services:
|
|||
environment:
|
||||
- DOCROOT
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Running phpunit
|
||||
|
||||
When you run the `phpunit` command, there are number of options you can pass to it such as `--filter`, `--testsuite` and `--group`, as well as the path to the tests to execute, such as `modules/custom`.
|
||||
When you run the `phpunit` command, there are number of options you can pass to
|
||||
it such as `--filter`, `--testsuite` and `--group`, as well as the path to the
|
||||
tests to execute, such as `modules/custom`.
|
||||
|
||||
I wanted to still be able to do this by running `fin phpunit <args>` so the commands can be customised when executed. However, as the first half of the command (`../vendor/bin/phpunit -c core`) is consistent, I can wrap that within my custom command and not need to type it every time.
|
||||
I wanted to still be able to do this by running `fin phpunit <args>` so the
|
||||
commands can be customised when executed. However, as the first half of the
|
||||
command (`../vendor/bin/phpunit -c core`) is consistent, I can wrap that within
|
||||
my custom command and not need to type it every time.
|
||||
|
||||
By using `"$@"` I can capture any additional arguments, such as the test directory path, and append them to the command to execute.
|
||||
By using `"$@"` I can capture any additional arguments, such as the test
|
||||
directory path, and append them to the command to execute.
|
||||
|
||||
I’m using `$PROJECT_ROOT` to prefix the command with the absolute path to `phpunit` so that I don’t need to be in that directory when I run the custom command, and `$DOCROOT` to always enter the sub-directory where Drupal is located. In this case, it’s "docroot" though I also use "web" and I’ve seen various others used.
|
||||
I’m using `$PROJECT_ROOT` to prefix the command with the absolute path to
|
||||
`phpunit` so that I don’t need to be in that directory when I run the custom
|
||||
command, and `$DOCROOT` to always enter the sub-directory where Drupal is
|
||||
located. In this case, it’s "docroot" though I also use "web" and I’ve seen
|
||||
various others used.
|
||||
|
||||
```bash
|
||||
DOCROOT_PATH="${PROJECT_ROOT}/${DOCROOT}"
|
||||
|
@ -157,9 +200,12 @@ DRUPAL_CORE_PATH="${DOCROOT_PATH}/core"
|
|||
${PROJECT_ROOT}/vendor/bin/phpunit -c ${DRUPAL_CORE_PATH} "$@"
|
||||
```
|
||||
|
||||
For example, `fin phpunit modules/custom` would execute `/var/www/vendor/bin/phpunit -c /var/www/docroot/core modules/custom` within the container.
|
||||
For example, `fin phpunit modules/custom` would execute
|
||||
`/var/www/vendor/bin/phpunit -c /var/www/docroot/core modules/custom` within the
|
||||
container.
|
||||
|
||||
I can then wrap this within a condition so that the tests are only run when a `phpunit.xml` file exists, as it is required for them to run successfully.
|
||||
I can then wrap this within a condition so that the tests are only run when a
|
||||
`phpunit.xml` file exists, as it is required for them to run successfully.
|
||||
|
||||
```bash
|
||||
if [ ! -e ${DRUPAL_CORE_PATH}/phpunit.xml ]; then
|
||||
|
@ -171,9 +217,14 @@ fi
|
|||
|
||||
### Creating phpunit.xml - step 1
|
||||
|
||||
My first thought was that if a `phpunit.xml` file doesn’t exist was to duplicate core’s `phpunit.xml.dist` file. However this isn’t enough to run the tests, as values such as `SIMPLETEST_BASE_URL`, `SIMPLETEST_DB` and `BROWSERTEST_OUTPUT_DIRECTORY` need to be populated.
|
||||
My first thought was that if a `phpunit.xml` file doesn’t exist was to duplicate
|
||||
core’s `phpunit.xml.dist` file. However this isn’t enough to run the tests, as
|
||||
values such as `SIMPLETEST_BASE_URL`, `SIMPLETEST_DB` and
|
||||
`BROWSERTEST_OUTPUT_DIRECTORY` need to be populated.
|
||||
|
||||
As the tests wouldn't run at this point, I’ve exited early and displayed a message to the user to edit the new `phpunit.xml` file and run `fin phpunit` again.
|
||||
As the tests wouldn't run at this point, I’ve exited early and displayed a
|
||||
message to the user to edit the new `phpunit.xml` file and run `fin phpunit`
|
||||
again.
|
||||
|
||||
```bash
|
||||
if [ ! -e ${DRUPAL_CORE_PATH}/phpunit.xml ]; then
|
||||
|
@ -186,17 +237,25 @@ else
|
|||
fi
|
||||
```
|
||||
|
||||
However this isn’t as streamlined as I originally wanted as it still requires the user to perform an additional step before the tests can run.
|
||||
However this isn’t as streamlined as I originally wanted as it still requires
|
||||
the user to perform an additional step before the tests can run.
|
||||
|
||||
### Creating phpunit.xml - step 2
|
||||
|
||||
My second idea was to keep a pre-configured file within the project repository, and to copy that into the expected location. That approach would mean that the project specific values would already be populated, as well as any customisations made to the default settings. I decided on `.docksal/drupal/core/phpunit.xml` to be the potential location.
|
||||
My second idea was to keep a pre-configured file within the project repository,
|
||||
and to copy that into the expected location. That approach would mean that the
|
||||
project specific values would already be populated, as well as any
|
||||
customisations made to the default settings. I decided on
|
||||
`.docksal/drupal/core/phpunit.xml` to be the potential location.
|
||||
|
||||
Also, if this file is copied then we can go ahead and run the tests straight away rather than needing to exit early.
|
||||
Also, if this file is copied then we can go ahead and run the tests straight
|
||||
away rather than needing to exit early.
|
||||
|
||||
If a pre-configured file doesn’t exist, then we can default back to copying `phpunit.xml.dist`.
|
||||
If a pre-configured file doesn’t exist, then we can default back to copying
|
||||
`phpunit.xml.dist`.
|
||||
|
||||
To avoid duplication, I created a reusable `run_tests()` function so it could be executed in either scenario.
|
||||
To avoid duplication, I created a reusable `run_tests()` function so it could be
|
||||
executed in either scenario.
|
||||
|
||||
```bash
|
||||
run_tests() {
|
||||
|
@ -219,7 +278,9 @@ else
|
|||
fi
|
||||
```
|
||||
|
||||
This means that I can execute less steps and run a much shorter command compared to the original, and even if someone didn’t have a `phpunit.xml` file created they could have copied into place and have tests running with only one command.
|
||||
This means that I can execute less steps and run a much shorter command compared
|
||||
to the original, and even if someone didn’t have a `phpunit.xml` file created
|
||||
they could have copied into place and have tests running with only one command.
|
||||
|
||||
## The finished file
|
||||
|
||||
|
@ -259,11 +320,20 @@ else
|
|||
fi
|
||||
```
|
||||
|
||||
It’s currently available as a [GitHub Gist][2], though I’m planning on moving it into a public GitHub repository either on my personal account or the [Microserve organisation][3], for people to either use as examples or to download and use directly.
|
||||
It’s currently available as a [GitHub Gist][2], though I’m planning on moving it
|
||||
into a public GitHub repository either on my personal account or the [Microserve
|
||||
organisation][3], for people to either use as examples or to download and use
|
||||
directly.
|
||||
|
||||
I’ve also started to add other commands to projects such as `config-export` to standardise the way to export configuration from Drupal 8, run Drupal 7 tests with SimpleTest, and compile front-end assets like CSS within custom themes.
|
||||
I’ve also started to add other commands to projects such as `config-export` to
|
||||
standardise the way to export configuration from Drupal 8, run Drupal 7 tests
|
||||
with SimpleTest, and compile front-end assets like CSS within custom themes.
|
||||
|
||||
I think it’s a great way to shorten existing commands, or to group multiple commands into one like in this case, and I can see a lot of other potential uses for it during local development and continuous integration. Also being able to run one command like `fin init` and have it set up everything for your project is very convenient and a big time saver!
|
||||
I think it’s a great way to shorten existing commands, or to group multiple
|
||||
commands into one like in this case, and I can see a lot of other potential uses
|
||||
for it during local development and continuous integration. Also being able to
|
||||
run one command like `fin init` and have it set up everything for your project
|
||||
is very convenient and a big time saver!
|
||||
|
||||
<div class="note" markdown="1">
|
||||
Since writing this post, I’ve had a [pull request][8] accepted for this command to be added as a [Docksal add-on][9]. This means that the command can be added to any Docksal project by running `fin addon install phpunit`. It will be installed into the `.docksal/addons/phpunit` directory, and displayed under "Addons" rather than "Custom commands" when you run `fin`.
|
||||
|
@ -275,7 +345,8 @@ Since writing this post, I’ve had a [pull request][8] accepted for this comman
|
|||
- [PHPUnit in Drupal 8][4]
|
||||
- [Main Docksal website](https://docksal.io)
|
||||
- [Docksal documentation](https://docksal.readthedocs.io)
|
||||
- [Docksal: one tool to rule local and CI/CD environments][1] - Docksal talk from Drupaldelphia
|
||||
- [Docksal: one tool to rule local and CI/CD environments][1] - Docksal talk
|
||||
from Drupaldelphia
|
||||
- [phpcs example custom command][5]
|
||||
- [phpunit command Gist][2]
|
||||
- [Docksal addons blog post][9]
|
||||
|
@ -286,7 +357,8 @@ Since writing this post, I’ve had a [pull request][8] accepted for this comman
|
|||
[2]: https://gist.github.com/opdavies/72611f198ffd2da13f363ea65264b2a5
|
||||
[3]: {{site.companies.microserve.github}}
|
||||
[4]: https://www.drupal.org/docs/8/phpunit
|
||||
[5]: https://github.com/docksal/docksal/blob/develop/examples/.docksal/commands/phpcs
|
||||
[5]:
|
||||
https://github.com/docksal/docksal/blob/develop/examples/.docksal/commands/phpcs
|
||||
[6]: /talks/tdd-test-driven-drupal
|
||||
[7]: /articles/tags/testing
|
||||
[8]: https://github.com/docksal/addons/pull/15
|
||||
|
|
|
@ -9,9 +9,19 @@ tags:
|
|||
- domain
|
||||
- table-prefixing
|
||||
---
|
||||
The [Domain Access project](https://drupal.org/project/domain "The Domain Access project on Drupal.org") is a suite of modules that provide tools for running a group of affiliated sites from one Drupal installation and a single shared database. The issue is that the domains are stored within the database so these are copied across when the data is migrated between environments, whereas the domains are obviously going to change.
|
||||
|
||||
Rather than changing the domain settings within the Domain module itself, the best solution I think is to use table prefixes and create a different domain table per environment. With a live, staging and local domains, the tables would be named as follows:
|
||||
The
|
||||
[Domain Access project](https://drupal.org/project/domain 'The Domain Access project on Drupal.org')
|
||||
is a suite of modules that provide tools for running a group of affiliated sites
|
||||
from one Drupal installation and a single shared database. The issue is that the
|
||||
domains are stored within the database so these are copied across when the data
|
||||
is migrated between environments, whereas the domains are obviously going to
|
||||
change.
|
||||
|
||||
Rather than changing the domain settings within the Domain module itself, the
|
||||
best solution I think is to use table prefixes and create a different domain
|
||||
table per environment. With a live, staging and local domains, the tables would
|
||||
be named as follows:
|
||||
|
||||
```language-bash
|
||||
live_domain
|
||||
|
@ -19,7 +29,9 @@ local_domain
|
|||
staging_domain
|
||||
```
|
||||
|
||||
Within each site's settings.php file, define the prefix for the domain table within the databases array so that each site is looking at the correct table for its environment.
|
||||
Within each site's settings.php file, define the prefix for the domain table
|
||||
within the databases array so that each site is looking at the correct table for
|
||||
its environment.
|
||||
|
||||
```language-php
|
||||
$databases['default']['default'] = array(
|
||||
|
@ -36,4 +48,5 @@ $databases['default']['default'] = array(
|
|||
);
|
||||
```
|
||||
|
||||
Within each environment-specific domain table, update the subdomain column to contain the appropriate domain names.
|
||||
Within each environment-specific domain table, update the subdomain column to
|
||||
contain the appropriate domain names.
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
---
|
||||
title: Croeso PHP South Wales!
|
||||
date: 2018-08-01
|
||||
excerpt: Last night was the first meetup of Cardiff’s PHP South Wales user group.
|
||||
excerpt:
|
||||
Last night was the first meetup of Cardiff’s PHP South Wales user group.
|
||||
tags:
|
||||
- php
|
||||
- php-south-wales
|
||||
- meetups
|
||||
- php
|
||||
- php-south-wales
|
||||
- meetups
|
||||
has_tweets: true
|
||||
---
|
||||
Last night was the first meetup of Cardiff’s [PHP South Wales user group][0]! It was a great first event, and it was great to meet a lot of new people as well as catch up some familiars within the 36 (according to meetup.com) attendees - including some [PHP South West][9] regulars.
|
||||
|
||||
Organised by Steve and Amy McDougall, it was held in Barclays’ [Eagle Lab][1] which was a great space, and it was cool to be back in Brunel House having worked in that building previously whilst at Appnovation.
|
||||
Last night was the first meetup of Cardiff’s [PHP South Wales user group][0]! It
|
||||
was a great first event, and it was great to meet a lot of new people as well as
|
||||
catch up some familiars within the 36 (according to meetup.com) attendees -
|
||||
including some [PHP South West][9] regulars.
|
||||
|
||||
Organised by Steve and Amy McDougall, it was held in Barclays’ [Eagle Lab][1]
|
||||
which was a great space, and it was cool to be back in Brunel House having
|
||||
worked in that building previously whilst at Appnovation.
|
||||
|
||||
{% include 'tweet' with {
|
||||
class: 'my-6',
|
||||
|
@ -20,7 +27,10 @@ Organised by Steve and Amy McDougall, it was held in Barclays’ [Eagle Lab][1]
|
|||
|
||||
## Speakers
|
||||
|
||||
[Rob Allen][2] was the main speaker, who gave an interesting talk and a brave live demo on serverless PHP and OpenWhisk. I always enjoy watching Rob speak, which I’ve done a number of times at different events, and it was great to be able to chat for a while after the meetup too.
|
||||
[Rob Allen][2] was the main speaker, who gave an interesting talk and a brave
|
||||
live demo on serverless PHP and OpenWhisk. I always enjoy watching Rob speak,
|
||||
which I’ve done a number of times at different events, and it was great to be
|
||||
able to chat for a while after the meetup too.
|
||||
|
||||
{% include 'tweet' with {
|
||||
class: 'my-6',
|
||||
|
@ -28,9 +38,14 @@ Organised by Steve and Amy McDougall, it was held in Barclays’ [Eagle Lab][1]
|
|||
content: '<p lang="en" dir="ltr">Great to see <a href="https://twitter.com/akrabat?ref_src=twsrc%5Etfw">@akrabat</a> speaking about serverless PHP at the first <a href="https://twitter.com/phpSouthWales?ref_src=twsrc%5Etfw">@phpSouthWales</a> meetup. <a href="https://twitter.com/hashtag/php?src=hash&ref_src=twsrc%5Etfw">#php</a> <a href="https://twitter.com/hashtag/phpc?src=hash&ref_src=twsrc%5Etfw">#phpc</a> <a href="https://twitter.com/hashtag/cardiff?src=hash&ref_src=twsrc%5Etfw">#cardiff</a> <a href="https://t.co/Q9YaQ6O1fB">pic.twitter.com/Q9YaQ6O1fB</a></p>— Oliver Davies (@opdavies) <a href="https://twitter.com/opdavies/status/1024359937063956484?ref_src=twsrc%5Etfw">July 31, 2018</a>',
|
||||
} %}
|
||||
|
||||
We also had a couple of lightning talks, starting with [Ismael Velasco][3] giving an introduction to progressive web applications (PWAs). I can see some potential uses for this on my current work project, and I look forward to seeing the full talk soon).
|
||||
We also had a couple of lightning talks, starting with [Ismael Velasco][3]
|
||||
giving an introduction to progressive web applications (PWAs). I can see some
|
||||
potential uses for this on my current work project, and I look forward to seeing
|
||||
the full talk soon).
|
||||
|
||||
I gave an updated version of my [Tailwind CSS lightning talk][4], and enjoyed being able to show some examples of new sites using Tailwind such as [Laravel Nova][5], [Spatie][6]’s new website and PHP South Wales itself!
|
||||
I gave an updated version of my [Tailwind CSS lightning talk][4], and enjoyed
|
||||
being able to show some examples of new sites using Tailwind such as [Laravel
|
||||
Nova][5], [Spatie][6]’s new website and PHP South Wales itself!
|
||||
|
||||
{% include 'tweet' with {
|
||||
class: 'my-6',
|
||||
|
@ -40,11 +55,19 @@ I gave an updated version of my [Tailwind CSS lightning talk][4], and enjoyed be
|
|||
|
||||
## Conclusion
|
||||
|
||||
It’s great to have a meetup in Cardiff again, and having thought about organsing something myself previously, I’m glad to see someone step forward to do so. This shows that there's still a strong PHP community in Cardiff and South Wales, and hopefully this will be the first meetup of many. I’ll look forward to seeing the local community grow!
|
||||
It’s great to have a meetup in Cardiff again, and having thought about organsing
|
||||
something myself previously, I’m glad to see someone step forward to do so. This
|
||||
shows that there's still a strong PHP community in Cardiff and South Wales, and
|
||||
hopefully this will be the first meetup of many. I’ll look forward to seeing the
|
||||
local community grow!
|
||||
|
||||
Thanks again to Steve and Amy for organising, Eagle Labs for hosting, the sponsors, and Rob and Ismael for speaking.
|
||||
Thanks again to Steve and Amy for organising, Eagle Labs for hosting, the
|
||||
sponsors, and Rob and Ismael for speaking.
|
||||
|
||||
It would be great to see even more people at the next one. If you’re interested, take a look at the [group’s website][0], [meetup.com group][7] and [Twitter profile][8]. Alternatively, get in touch with myself or one of the organisers for more information.
|
||||
It would be great to see even more people at the next one. If you’re interested,
|
||||
take a look at the [group’s website][0], [meetup.com group][7] and [Twitter
|
||||
profile][8]. Alternatively, get in touch with myself or one of the organisers
|
||||
for more information.
|
||||
|
||||
**Croeso ac iechyd da PHP South Wales!**
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
---
|
||||
title: Debugging Drupal Commerce Promotions and Adjustments using Illuminate Collections (Drupal 8)
|
||||
title:
|
||||
Debugging Drupal Commerce Promotions and Adjustments using Illuminate
|
||||
Collections (Drupal 8)
|
||||
date: 2018-10-24
|
||||
excerpt: Using Laravel’s Illuminate Collections to debug an issue with a Drupal Commerce promotion.
|
||||
excerpt:
|
||||
Using Laravel’s Illuminate Collections to debug an issue with a Drupal
|
||||
Commerce promotion.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-8
|
||||
|
@ -12,11 +16,18 @@ tags:
|
|||
- php
|
||||
promoted: true
|
||||
---
|
||||
Today I found another instance where I decided to use [Illuminate Collections][0] within my Drupal 8 code; whilst I was debugging an issue where a [Drupal Commerce][1] promotion was incorrectly being applied to an order.
|
||||
|
||||
No adjustments were showing in the Drupal UI for that order, so after some initial investigation and finding that `$order->getAdjustments()` was empty, I determined that I would need to get the adjustments from each order item within the order.
|
||||
Today I found another instance where I decided to use [Illuminate
|
||||
Collections][0] within my Drupal 8 code; whilst I was debugging an issue where a
|
||||
[Drupal Commerce][1] promotion was incorrectly being applied to an order.
|
||||
|
||||
If the order were an array, this is how it would be structured in this situation:
|
||||
No adjustments were showing in the Drupal UI for that order, so after some
|
||||
initial investigation and finding that `$order->getAdjustments()` was empty, I
|
||||
determined that I would need to get the adjustments from each order item within
|
||||
the order.
|
||||
|
||||
If the order were an array, this is how it would be structured in this
|
||||
situation:
|
||||
|
||||
```php
|
||||
$order = [
|
||||
|
@ -25,8 +36,8 @@ $order = [
|
|||
[
|
||||
'id' => 1,
|
||||
'adjustments' => [
|
||||
['name' => 'Adjustment 1'],
|
||||
['name' => 'Adjustment 2'],
|
||||
['name' => 'Adjustment 1'],
|
||||
['name' => 'Adjustment 2'],
|
||||
['name' => 'Adjustment 3'],
|
||||
]
|
||||
],
|
||||
|
@ -39,7 +50,7 @@ $order = [
|
|||
[
|
||||
'id' => 3,
|
||||
'adjustments' => [
|
||||
['name' => 'Adjustment 5'],
|
||||
['name' => 'Adjustment 5'],
|
||||
['name' => 'Adjustment 6'],
|
||||
]
|
||||
],
|
||||
|
@ -49,7 +60,9 @@ $order = [
|
|||
|
||||
## Getting the order items
|
||||
|
||||
I started by using `$order->getItems()` to load the order’s items, converted them into a Collection, and used the Collection’s `pipe()` method and the `dump()` function provided by the [Devel module][2] to output the order items.
|
||||
I started by using `$order->getItems()` to load the order’s items, converted
|
||||
them into a Collection, and used the Collection’s `pipe()` method and the
|
||||
`dump()` function provided by the [Devel module][2] to output the order items.
|
||||
|
||||
```php
|
||||
collect($order->getItems())
|
||||
|
@ -60,9 +73,13 @@ collect($order->getItems())
|
|||
|
||||
## Get the order item adjustments
|
||||
|
||||
Now we have a Collection of order items, for each item we need to get it’s adjustments. We can do this with `map()`, then call `getAdjustments()` on the order item.
|
||||
Now we have a Collection of order items, for each item we need to get it’s
|
||||
adjustments. We can do this with `map()`, then call `getAdjustments()` on the
|
||||
order item.
|
||||
|
||||
This would return a Collection of arrays, with each array containing it’s own adjustments, so we can use `flatten()` to collapse all the adjustments into one single-dimensional array.
|
||||
This would return a Collection of arrays, with each array containing it’s own
|
||||
adjustments, so we can use `flatten()` to collapse all the adjustments into one
|
||||
single-dimensional array.
|
||||
|
||||
```php
|
||||
collect($order->getItems())
|
||||
|
@ -75,7 +92,9 @@ collect($order->getItems())
|
|||
There are a couple of refactors that we can do here though:
|
||||
|
||||
- Use `flatMap()` to combine the `flatten()` and `map()` methods.
|
||||
- Use [higher order messages][3] to delegate straight to the `getAdjustments()` method on the order, rather than having to create a closure and call the method within it.
|
||||
- Use [higher order messages][3] to delegate straight to the `getAdjustments()`
|
||||
method on the order, rather than having to create a closure and call the
|
||||
method within it.
|
||||
|
||||
```php
|
||||
collect($order->getItems())
|
||||
|
@ -84,8 +103,10 @@ collect($order->getItems())
|
|||
|
||||
## Filtering
|
||||
|
||||
In this scenario, each order item had three adjustments - the correct promotion, the incorrect one and the standard VAT addition.
|
||||
I wasn’t concerned about the VAT adjustment for debugging, so I used `filter()` to remove it based on the result of the adjustment’s `getSourceId()` method.
|
||||
In this scenario, each order item had three adjustments - the correct promotion,
|
||||
the incorrect one and the standard VAT addition. I wasn’t concerned about the
|
||||
VAT adjustment for debugging, so I used `filter()` to remove it based on the
|
||||
result of the adjustment’s `getSourceId()` method.
|
||||
|
||||
```php
|
||||
collect($order->getItems())
|
||||
|
@ -97,9 +118,11 @@ collect($order->getItems())
|
|||
|
||||
## Conclusion
|
||||
|
||||
Now I have just the relevant adjustments, I want to be able to load each one to load it and check it’s conditions. To do this, I need just the source IDs.
|
||||
Now I have just the relevant adjustments, I want to be able to load each one to
|
||||
load it and check it’s conditions. To do this, I need just the source IDs.
|
||||
|
||||
Again, I can use a higher order message to directly call `getSourceId()` on the adjustment and return it’s value to `map()`.
|
||||
Again, I can use a higher order message to directly call `getSourceId()` on the
|
||||
adjustment and return it’s value to `map()`.
|
||||
|
||||
```php
|
||||
collect($order->getItems())
|
||||
|
@ -110,7 +133,8 @@ collect($order->getItems())
|
|||
->map->getSourceId();
|
||||
```
|
||||
|
||||
This returns a Collection containing just the relevant promotion IDs being applied to the order that I can use for debugging.
|
||||
This returns a Collection containing just the relevant promotion IDs being
|
||||
applied to the order that I can use for debugging.
|
||||
|
||||
Now just to find out why the incorrect promotion was applying!
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ tags:
|
|||
- php
|
||||
- aria
|
||||
---
|
||||
For reference, this is the code needed to display a menu in a Drupal 7 template file, including the navigation ARIA role.
|
||||
|
||||
For reference, this is the code needed to display a menu in a Drupal 7 template
|
||||
file, including the navigation ARIA role.
|
||||
|
||||
```language-php
|
||||
$menu_name = 'menu-footer-menu';
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
---
|
||||
title: Display Git Branch or Tag Names in your Bash Prompt
|
||||
date: 2013-04-27
|
||||
excerpt: Whilst watching Drupalize.me's recent Introduction to Git series, I thought it was useful the way that the current Git branch or tag name was displayed in the bash prompt. Here's how to do it.
|
||||
excerpt:
|
||||
Whilst watching Drupalize.me's recent Introduction to Git series, I thought it
|
||||
was useful the way that the current Git branch or tag name was displayed in
|
||||
the bash prompt. Here's how to do it.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- git
|
||||
- terminal
|
||||
---
|
||||
Whilst watching [Drupalize.me](http://drupalize.me "Drupalize.me")'s recent [Introduction to Git series](http://drupalize.me/series/introduction-git-series "Introduction to Git on Drupalize.me"), I thought it was useful the way that the current Git branch or tag name was displayed in the bash prompt.
|
||||
|
||||
Whilst watching [Drupalize.me](http://drupalize.me 'Drupalize.me')'s recent
|
||||
[Introduction to Git series](http://drupalize.me/series/introduction-git-series 'Introduction to Git on Drupalize.me'),
|
||||
I thought it was useful the way that the current Git branch or tag name was
|
||||
displayed in the bash prompt.
|
||||
|
||||
Here's how to do it.
|
||||
|
||||
|
@ -37,7 +44,7 @@ parse_git_branch () {
|
|||
parse_git_tag () {
|
||||
git describe --tags 2> /dev/null
|
||||
}
|
||||
|
||||
|
||||
parse_git_branch_or_tag() {
|
||||
local OUT="$(parse_git_branch)"
|
||||
if [ "$OUT" == " ((no branch))" ]; then
|
||||
|
@ -53,7 +60,7 @@ Edit your `.bashrc` or `.bash_profile` file to override the PS1 value.
|
|||
vim ~/.bashrc
|
||||
```
|
||||
|
||||
Add the following code at the bottom of the file, and save it.
|
||||
Add the following code at the bottom of the file, and save it.
|
||||
|
||||
```language-bash
|
||||
source ~/.bash/git-prompt
|
||||
|
|
|
@ -5,11 +5,19 @@ excerpt: How to use PHP to display the number of fans of a Facebook page.
|
|||
tags:
|
||||
- php
|
||||
---
|
||||
Replace the $page_id value with your Page ID number (unless you want to show the number of fans for this site).You can find your Page ID by logging into your Facebook account, going to 'Adverts and Pages', clicking 'Edit page', and looking at the URL.
|
||||
|
||||
For example, mine is <https://www.facebook.com/pages/edit/?id=143394365692197&sk=basic>.
|
||||
Replace the \$page_id value with your Page ID number (unless you want to show
|
||||
the number of fans for this site).You can find your Page ID by logging into your
|
||||
Facebook account, going to 'Adverts and Pages', clicking 'Edit page', and
|
||||
looking at the URL.
|
||||
|
||||
I've also wrapped the output in a number_format() function so that it properly formatted with commas etc - like where I've used it within the [Gold Event listing](http://www.horseandcountry.tv/events/paid) on the Horse & Country TV website.
|
||||
For example, mine is
|
||||
<https://www.facebook.com/pages/edit/?id=143394365692197&sk=basic>.
|
||||
|
||||
I've also wrapped the output in a number_format() function so that it properly
|
||||
formatted with commas etc - like where I've used it within the
|
||||
[Gold Event listing](http://www.horseandcountry.tv/events/paid) on the Horse &
|
||||
Country TV website.
|
||||
|
||||
```language-php
|
||||
$page_id = "143394365692197";
|
||||
|
@ -18,4 +26,5 @@ $fans = $xml->page->fan_count;
|
|||
print number_format($fans);
|
||||
```
|
||||
|
||||
This code was originally found at <http://wp-snippets.com/display-number-facebook-fans>.
|
||||
This code was originally found at
|
||||
<http://wp-snippets.com/display-number-facebook-fans>.
|
||||
|
|
|
@ -1,23 +1,36 @@
|
|||
---
|
||||
title: Dividing Drupal's process and preprocess functions into separate files
|
||||
date: 2012-05-24
|
||||
excerpt: If you use a lot of process and preprocess functions within your Drupal theme, then your template.php can get very long and it can become difficult to find a certain piece of code. Following the example of the Omega theme, I've started separating my process and preprocess functions into their own files.
|
||||
excerpt:
|
||||
If you use a lot of process and preprocess functions within your Drupal theme,
|
||||
then your template.php can get very long and it can become difficult to find a
|
||||
certain piece of code. Following the example of the Omega theme, I've started
|
||||
separating my process and preprocess functions into their own files.
|
||||
tags:
|
||||
- drupal
|
||||
- code
|
||||
- theming
|
||||
- preprocessing
|
||||
---
|
||||
If you use a lot of process and preprocess functions within your Drupal theme, then your template.php can get very long and it can become difficult to find a certain piece of code. Following the example of the [Omega theme](http://drupal.org/project/omega "The Omega theme on Drupal.org"), I've started separating my process and preprocess functions into their own files. For example, mytheme_preprocess_node can be placed within a preprocess/node.inc file, and mytheme_process_page can be placed within process/page.inc.
|
||||
|
||||
The first step is to use the default mytheme_process() and mytheme_preprocess() functions to utilise my custom function. So within my template.php file:
|
||||
If you use a lot of process and preprocess functions within your Drupal theme,
|
||||
then your template.php can get very long and it can become difficult to find a
|
||||
certain piece of code. Following the example of the
|
||||
[Omega theme](http://drupal.org/project/omega 'The Omega theme on Drupal.org'),
|
||||
I've started separating my process and preprocess functions into their own
|
||||
files. For example, mytheme_preprocess_node can be placed within a
|
||||
preprocess/node.inc file, and mytheme_process_page can be placed within
|
||||
process/page.inc.
|
||||
|
||||
The first step is to use the default mytheme_process() and mytheme_preprocess()
|
||||
functions to utilise my custom function. So within my template.php file:
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess().
|
||||
*
|
||||
*
|
||||
* Initialises the mytheme_invoke() function for the preprocess hook.
|
||||
*/
|
||||
function mytheme_preprocess(&$variables, $hook) {
|
||||
|
@ -26,7 +39,7 @@ function mytheme_preprocess(&$variables, $hook) {
|
|||
|
||||
/**
|
||||
* Implements hook_process().
|
||||
*
|
||||
*
|
||||
* Initialises the mytheme_invoke() function for the process hook.
|
||||
*/
|
||||
function mytheme_process(&$variables, $hook) {
|
||||
|
@ -50,17 +63,17 @@ Now, to write the `mytheme_invoke()` function:
|
|||
*
|
||||
* @param string $hook
|
||||
* The name of the hook.
|
||||
*
|
||||
* @see mytheme_preprocess()
|
||||
*
|
||||
* @see mytheme_preprocess()
|
||||
* @see mytheme_process()
|
||||
*/
|
||||
function mytheme_invoke($type, $hook, &$variables) {
|
||||
global $theme_key;
|
||||
|
||||
|
||||
// The name of the function to look for (e.g. mytheme_process_node).
|
||||
$function = $theme_key . '_' . $type . '_' . $hook;
|
||||
|
||||
// If the function doesn't exist within template.php, look for the
|
||||
// If the function doesn't exist within template.php, look for the
|
||||
// appropriate include file.
|
||||
if (!function_exists($function)) {
|
||||
// The file to search for (e.g. process/node.inc).
|
||||
|
@ -79,4 +92,6 @@ function mytheme_invoke($type, $hook, &$variables) {
|
|||
}
|
||||
```
|
||||
|
||||
As `mytheme_invoke()` checks to see if the function already exists before searching for checking the include files, I could still add the functions into template.php as normal and this would override any corresponding include file.
|
||||
As `mytheme_invoke()` checks to see if the function already exists before
|
||||
searching for checking the include files, I could still add the functions into
|
||||
template.php as normal and this would override any corresponding include file.
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
---
|
||||
title: Don't Bootstrap Drupal, Use Drush
|
||||
date: 2013-11-19
|
||||
excerpt: Avoid bootstrapping Drupal manually in your scratch files - Drush has you covered!
|
||||
excerpt:
|
||||
Avoid bootstrapping Drupal manually in your scratch files - Drush has you
|
||||
covered!
|
||||
tags:
|
||||
- drush
|
||||
- drupal-planet
|
||||
- php
|
||||
---
|
||||
There are times when doing Drupal development when you need to run a custom PHP script, maybe moving data from one field to another, that doesn't warrant the time and effort to create a custom module. In this scenario, it would be quicker to write a .php script and bootstrap Drupal to gain access to functions like `node_load()` and `db_query()`.
|
||||
|
||||
To bootstrap Drupal, you would need to add some additional lines of code to the stop of your script. Here is an alternative way.
|
||||
There are times when doing Drupal development when you need to run a custom PHP
|
||||
script, maybe moving data from one field to another, that doesn't warrant the
|
||||
time and effort to create a custom module. In this scenario, it would be quicker
|
||||
to write a .php script and bootstrap Drupal to gain access to functions like
|
||||
`node_load()` and `db_query()`.
|
||||
|
||||
To bootstrap Drupal, you would need to add some additional lines of code to the
|
||||
stop of your script. Here is an alternative way.
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
|
@ -24,29 +32,44 @@ drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
|
|||
$node = node_load(1);
|
||||
```
|
||||
|
||||
The script would need be placed in the root of your Drupal directory, and you would then have had to open a browser window and visit http://example.com/foo.php to execute it. This is where the "drush php-script" command (or "drush scr" for short) is useful, and can be used to execute the script from the command line.
|
||||
The script would need be placed in the root of your Drupal directory, and you
|
||||
would then have had to open a browser window and visit
|
||||
http://example.com/foo.php to execute it. This is where the "drush php-script"
|
||||
command (or "drush scr" for short) is useful, and can be used to execute the
|
||||
script from the command line.
|
||||
|
||||
```language-bash
|
||||
$ drush scr foo.php
|
||||
```
|
||||
|
||||
It also means that I no longer need to manually bootstrap Drupal, so my script is much cleaner.
|
||||
It also means that I no longer need to manually bootstrap Drupal, so my script
|
||||
is much cleaner.
|
||||
|
||||
```language-php
|
||||
// Just do stuff.
|
||||
$node = node_load(1);
|
||||
```
|
||||
|
||||
I prefer to keep these scripts outside of my Drupal directory in a separate "scripts" directory (with Drupal in a "drupal" directory on the same level). This makes it easier to update Drupal as I don't need to worry about accidentally deleting the additional files. From within the drupal directory, I can now run the following command to go up one level, into the scripts directory and then execute the script. Note that you do not need to include the file extension.
|
||||
I prefer to keep these scripts outside of my Drupal directory in a separate
|
||||
"scripts" directory (with Drupal in a "drupal" directory on the same level).
|
||||
This makes it easier to update Drupal as I don't need to worry about
|
||||
accidentally deleting the additional files. From within the drupal directory, I
|
||||
can now run the following command to go up one level, into the scripts directory
|
||||
and then execute the script. Note that you do not need to include the file
|
||||
extension.
|
||||
|
||||
```language-bash
|
||||
$ drush scr ../scripts/foo
|
||||
```
|
||||
|
||||
Or, if you're using [Drush aliases](http://deeson-online.co.uk/labs/drupal-drush-aliases-and-how-use-them "Drupal, Drush aliases, and how to use them"):
|
||||
Or, if you're using
|
||||
[Drush aliases](http://deeson-online.co.uk/labs/drupal-drush-aliases-and-how-use-them 'Drupal, Drush aliases, and how to use them'):
|
||||
|
||||
```language-bash
|
||||
$ drush @mysite.local scr foo
|
||||
```
|
||||
|
||||
If you commonly use the same scripts for different projects, you could also store these within a separate Git repository and checkout the scripts directory using a [Git submodule](http://git-scm.com/book/en/Git-Tools-Submodules "Git Submodules").
|
||||
If you commonly use the same scripts for different projects, you could also
|
||||
store these within a separate Git repository and checkout the scripts directory
|
||||
using a
|
||||
[Git submodule](http://git-scm.com/book/en/Git-Tools-Submodules 'Git Submodules').
|
||||
|
|
|
@ -7,19 +7,32 @@ tags:
|
|||
- drupal-planet
|
||||
- drush
|
||||
---
|
||||
If you use [Drush](https://raw.github.com/drush-ops/drush/master/README.md "About Drush"), it's likely that you've used the `drush pm-download` (or `drush dl` for short) command to start a new project. This command downloads projects from Drupal.org, but if you don't specify a project or type "drush dl drupal", the command will download the current stable version of Drupal core. Currently, this will be Drupal 7 with that being the current stable version of core at the time of writing this post.
|
||||
|
||||
If you use
|
||||
[Drush](https://raw.github.com/drush-ops/drush/master/README.md 'About Drush'),
|
||||
it's likely that you've used the `drush pm-download` (or `drush dl` for short)
|
||||
command to start a new project. This command downloads projects from Drupal.org,
|
||||
but if you don't specify a project or type "drush dl drupal", the command will
|
||||
download the current stable version of Drupal core. Currently, this will be
|
||||
Drupal 7 with that being the current stable version of core at the time of
|
||||
writing this post.
|
||||
|
||||
But what if you don't want Drupal 7?
|
||||
|
||||
I still maintain a number of Drupal 6 sites and occassionally need to download Drupal 6 core as opposed to Drupal 7. I'm also experimenting with Drupal 8 so I need to download that as well.
|
||||
I still maintain a number of Drupal 6 sites and occassionally need to download
|
||||
Drupal 6 core as opposed to Drupal 7. I'm also experimenting with Drupal 8 so I
|
||||
need to download that as well.
|
||||
|
||||
By declarding the core version of Drupal, such as "drupal-6", Drush will download that instead.
|
||||
By declarding the core version of Drupal, such as "drupal-6", Drush will
|
||||
download that instead.
|
||||
|
||||
```language-bash
|
||||
$ drush dl drupal-6
|
||||
```
|
||||
|
||||
This downloads the most recent stable version of Drupal 6. If you don't want that, you can add the --select and additionally the --all options to be presented with an entire list to chose from.
|
||||
This downloads the most recent stable version of Drupal 6. If you don't want
|
||||
that, you can add the --select and additionally the --all options to be
|
||||
presented with an entire list to chose from.
|
||||
|
||||
```language-bash
|
||||
$ drush dl drupal-6 --select
|
||||
|
@ -41,4 +54,6 @@ $ drush dl drupal-5
|
|||
$ drush dl drupal-8
|
||||
```
|
||||
|
||||
For a full list of the available options, type "drush help pm-download" into a Terminal window or take a look at the entry on [drush.ws](http://drush.ws/#pm-download, "The entry for pm-download on drush.ws").
|
||||
For a full list of the available options, type "drush help pm-download" into a
|
||||
Terminal window or take a look at the entry on
|
||||
[drush.ws](http://drush.ws/#pm-download, 'The entry for pm-download on drush.ws').
|
||||
|
|
|
@ -3,16 +3,30 @@ title: 'Drupal 8.5.0 Released'
|
|||
date: 2018-03-09
|
||||
excerpt: This week, the latest version of Drupal 8 was released.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-core
|
||||
- drupal
|
||||
- drupal-core
|
||||
---
|
||||
|
||||
This week the latest minor version of Drupal 8, 8.5.0, was released.
|
||||
|
||||
> This new version makes Media module available for all, improves migrations significantly, stabilizes the Content Moderation and Settings Tray modules, serves dynamic pages faster with BigPipe enabled by default, and introduces a new experimental entity layout user interface. The release includes several very important fixes for workflows of content translations and supports running on PHP 7.2.
|
||||
> This new version makes Media module available for all, improves migrations
|
||||
> significantly, stabilizes the Content Moderation and Settings Tray modules,
|
||||
> serves dynamic pages faster with BigPipe enabled by default, and introduces a
|
||||
> new experimental entity layout user interface. The release includes several
|
||||
> very important fixes for workflows of content translations and supports
|
||||
> running on PHP 7.2.
|
||||
|
||||
I’ve been very impressed by the new release cycle Drupal 8 and the usage of semantic versioning. Though it adds a greater maintenance overhead for module, theme, installation profile and distribution developers to ensure that our projects are still working properly, having the ability to add new modules into Drupal core as well as new installation profiles like the [Unami demonstration profile][2] is pretty cool!
|
||||
I’ve been very impressed by the new release cycle Drupal 8 and the usage of
|
||||
semantic versioning. Though it adds a greater maintenance overhead for module,
|
||||
theme, installation profile and distribution developers to ensure that our
|
||||
projects are still working properly, having the ability to add new modules into
|
||||
Drupal core as well as new installation profiles like the [Unami demonstration
|
||||
profile][2] is pretty cool!
|
||||
|
||||
For example, in addition to Unami, 8.5 alone adds media in core, two experimental modules have been marked as stable, an experimental new layout builder has been added and lots of PHP 7.2 improvements have been committed to make 8.5 fully PHP 7.2 compatible.
|
||||
For example, in addition to Unami, 8.5 alone adds media in core, two
|
||||
experimental modules have been marked as stable, an experimental new layout
|
||||
builder has been added and lots of PHP 7.2 improvements have been committed to
|
||||
make 8.5 fully PHP 7.2 compatible.
|
||||
|
||||
I’m already looking forward to see what’s coming in 8.6 later this year!
|
||||
|
||||
|
@ -20,4 +34,5 @@ For more information on the 8.5 release, see the [blog post on Drupal.org][1].
|
|||
|
||||
[0]: https://dri.es/drupal-8-5-0-released
|
||||
[1]: https://www.drupal.org/blog/drupal-8-5-0
|
||||
[2]: https://www.drupal.org/docs/8/umami-drupal-8-demonstration-installation-profile
|
||||
[2]:
|
||||
https://www.drupal.org/docs/8/umami-drupal-8-demonstration-installation-profile
|
||||
|
|
|
@ -1,30 +1,44 @@
|
|||
---
|
||||
title: "Drupal 8 Commerce: Fixing 'No Such Customer' error on checkout"
|
||||
date: 2018-08-15
|
||||
excerpt: Fixing a Drupal Commerce error when a user tries to complete a checkout.
|
||||
excerpt:
|
||||
Fixing a Drupal Commerce error when a user tries to complete a checkout.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-commerce
|
||||
- stripe
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-commerce
|
||||
- stripe
|
||||
---
|
||||
Recently I was experiencing an issue on the Drupal 8 website I’m working on, where a small number of users were not able to complete the checkout process and instead got a generic `The site has encountered an unexpected error` message.
|
||||
|
||||
Looking at the log, I was able to see the error being thrown (the customer ID has been redacted):
|
||||
Recently I was experiencing an issue on the Drupal 8 website I’m working on,
|
||||
where a small number of users were not able to complete the checkout process and
|
||||
instead got a generic `The site has encountered an unexpected error` message.
|
||||
|
||||
> Stripe\Error\InvalidRequest: No such customer: cus_xxxxxxxxxxxxxx in Stripe\ApiRequestor::_specificAPIError() (line 124 of /var/www/vendor/stripe/stripe-php/lib/ApiRequestor.php).
|
||||
Looking at the log, I was able to see the error being thrown (the customer ID
|
||||
has been redacted):
|
||||
|
||||
Logging in to the Stripe account, I was able to confirm that the specified customer ID did not exist. So where was it coming from, and why was Drupal trying to retrieve a non-existent customer?
|
||||
> Stripe\Error\InvalidRequest: No such customer: cus_xxxxxxxxxxxxxx in
|
||||
> Stripe\ApiRequestor::\_specificAPIError() (line 124 of
|
||||
> /var/www/vendor/stripe/stripe-php/lib/ApiRequestor.php).
|
||||
|
||||
Logging in to the Stripe account, I was able to confirm that the specified
|
||||
customer ID did not exist. So where was it coming from, and why was Drupal
|
||||
trying to retrieve a non-existent customer?
|
||||
|
||||
## Investigation
|
||||
|
||||
After some investigation, I found a table in the database named `user__commerce_remote_id` which stores the remote customer ID for each payment method (again, the customer ID has been redacted).
|
||||
After some investigation, I found a table in the database named
|
||||
`user__commerce_remote_id` which stores the remote customer ID for each payment
|
||||
method (again, the customer ID has been redacted).
|
||||
|
||||
![A screenshot of a row in the user__commerce_remote_id table](/images/blog/commerce-stripe-error/remote-id-table.png){.border.p-1}
|
||||
|
||||
The `entity_id` and `revision_id` values in this case refer to the user that the Stripe customer has been associated with.
|
||||
The `entity_id` and `revision_id` values in this case refer to the user that the
|
||||
Stripe customer has been associated with.
|
||||
|
||||
As there was no customer in Stripe with this ID, I think that this must be a customer ID from the test environment (the data from which was deleted before the site went live).
|
||||
As there was no customer in Stripe with this ID, I think that this must be a
|
||||
customer ID from the test environment (the data from which was deleted before
|
||||
the site went live).
|
||||
|
||||
### Drupal code
|
||||
|
||||
|
@ -77,4 +91,6 @@ private static function _specificAPIError($rbody, $rcode, $rheaders, $resp, $err
|
|||
|
||||
## Solution
|
||||
|
||||
After confirming that it was the correct user ID, simply removing that row from the database allowed the new Stripe customer to be created and for the user to check out successfully.
|
||||
After confirming that it was the correct user ID, simply removing that row from
|
||||
the database allowed the new Stripe customer to be created and for the user to
|
||||
check out successfully.
|
||||
|
|
|
@ -6,14 +6,32 @@ tags:
|
|||
- drupal
|
||||
- personal
|
||||
---
|
||||
Today was my last day working at [Precedent](http://www.precedent.com). Next week, I'll be starting my [new job](https://assoc.drupal.org/node/18923 "Drupal.org Developer") at the [Drupal Association](http://assoc.drupal.org) working on Drupal's home - [Drupal.org](http://www.drupal.org).
|
||||
|
||||
I was at Precedent for just over a year and had the opportunity to work on several Drupal projects from project leading to ad-hoc module and theme development, including my largest Drupal build to date.
|
||||
Today was my last day working at [Precedent](http://www.precedent.com). Next
|
||||
week, I'll be starting my
|
||||
[new job](https://assoc.drupal.org/node/18923 'Drupal.org Developer') at the
|
||||
[Drupal Association](http://assoc.drupal.org) working on Drupal's home -
|
||||
[Drupal.org](http://www.drupal.org).
|
||||
|
||||
I was also lucky enough to go to [DrupalCon Prague](http://prague2013.drupal.org) as well as [DrupalCamp London](http://2014.drupalcamplondon.co.uk).
|
||||
I was at Precedent for just over a year and had the opportunity to work on
|
||||
several Drupal projects from project leading to ad-hoc module and theme
|
||||
development, including my largest Drupal build to date.
|
||||
|
||||
I was able to [contribute some code](https://drupal.org/project/eventsforce) back into the community and encourage other team members to do the same.
|
||||
I was also lucky enough to go to
|
||||
[DrupalCon Prague](http://prague2013.drupal.org) as well as
|
||||
[DrupalCamp London](http://2014.drupalcamplondon.co.uk).
|
||||
|
||||
It was good to be able to introduce some new tools like [Vagrant](http://www.vagrantup.com), [Puppet](http://www.puppetlabs.com), [SASS](http://www.sass-lang.com) and [Compass](http://www.compass-style.org) into the team. I was pleased to introduce and champion the [Git Flow](http://danielkummer.github.io/git-flow-cheatsheet "Git Flow Cheat Sheet") branching model, which them became the standard approach for all Drupal projects, and hopefully soon all development projects.
|
||||
I was able to [contribute some code](https://drupal.org/project/eventsforce)
|
||||
back into the community and encourage other team members to do the same.
|
||||
|
||||
Working for the Drupal Association and on Drupal.org was an opportunity that I couldn't refuse, and is certainly going to be a fun and interesting challenge. I can't wait to get started!
|
||||
It was good to be able to introduce some new tools like
|
||||
[Vagrant](http://www.vagrantup.com), [Puppet](http://www.puppetlabs.com),
|
||||
[SASS](http://www.sass-lang.com) and [Compass](http://www.compass-style.org)
|
||||
into the team. I was pleased to introduce and champion the
|
||||
[Git Flow](http://danielkummer.github.io/git-flow-cheatsheet 'Git Flow Cheat Sheet')
|
||||
branching model, which them became the standard approach for all Drupal
|
||||
projects, and hopefully soon all development projects.
|
||||
|
||||
Working for the Drupal Association and on Drupal.org was an opportunity that I
|
||||
couldn't refuse, and is certainly going to be a fun and interesting challenge. I
|
||||
can't wait to get started!
|
||||
|
|
|
@ -1,34 +1,69 @@
|
|||
---
|
||||
title: Drupal Bristol Testing Workshop
|
||||
date: 2018-06-28
|
||||
excerpt: Yesterday evening, I did my first workshop, held at the Drupal Bristol user group.
|
||||
tags: [composer, docksal, drupal, drupal-8, drupal-bristol, php, phpunit, testing]
|
||||
excerpt:
|
||||
Yesterday evening, I did my first workshop, held at the Drupal Bristol user
|
||||
group.
|
||||
tags:
|
||||
[composer, docksal, drupal, drupal-8, drupal-bristol, php, phpunit, testing]
|
||||
---
|
||||
Yesterday evening, I did [my first workshop][16] (and I believe, the first workshop) held at the [{{ site.events['drupal_bristol'].name }}][14] user group. The subject was automated testing with PHPUnit in Drupal 8, in preparation for my talk at [{{ site.events['drupal_dev_days_18'].name }}][12] next week and to help process some ideas for my [testing book][15].
|
||||
|
||||
Yesterday evening, I did [my first workshop][16] (and I believe, the first
|
||||
workshop) held at the [{{ site.events['drupal_bristol'].name }}][14] user group.
|
||||
The subject was automated testing with PHPUnit in Drupal 8, in preparation for
|
||||
my talk at [{{ site.events['drupal_dev_days_18'].name }}][12] next week and to
|
||||
help process some ideas for my [testing book][15].
|
||||
|
||||
Here are some details about what we covered, and some of my thoughts in review.
|
||||
|
||||
## Local Environment
|
||||
|
||||
Before the meetup, I set up a [repository on GitHub][0] that contains a Composer-based Drupal 8 installation, based on the [Drupal 8 Composer template][4] along with the [Examples module][5] (which includes some PHPUnit tests) with a pre-configured [Docksal][2] environment to use locally - Docksal being our standard local development environment that we use at {{ site.companies['microserve'].name }} for all of our projects, so something that I’m familiar with using.
|
||||
Before the meetup, I set up a [repository on GitHub][0] that contains a
|
||||
Composer-based Drupal 8 installation, based on the [Drupal 8 Composer
|
||||
template][4] along with the [Examples module][5] (which includes some PHPUnit
|
||||
tests) with a pre-configured [Docksal][2] environment to use locally - Docksal
|
||||
being our standard local development environment that we use at
|
||||
{{ site.companies['microserve'].name }} for all of our projects, so something
|
||||
that I’m familiar with using.
|
||||
|
||||
In addition to the default stack, I added [the PHPUnit add-on that I wrote][6] so that it was easier to run tests, [configured settings.php using environment variables][7] and added a custom `fin init` command to install the Composer dependencies and install Drupal. This meant after that installing Docksal, everyone had a running Drupal 8 website after only running `git clone` and `fin init`, and could then run tests straight away using `fin phpunit web/modules/contrib/examples/phpunit_example`.
|
||||
In addition to the default stack, I added [the PHPUnit add-on that I wrote][6]
|
||||
so that it was easier to run tests, [configured settings.php using environment
|
||||
variables][7] and added a custom `fin init` command to install the Composer
|
||||
dependencies and install Drupal. This meant after that installing Docksal,
|
||||
everyone had a running Drupal 8 website after only running `git clone` and
|
||||
`fin init`, and could then run tests straight away using
|
||||
`fin phpunit web/modules/contrib/examples/phpunit_example`.
|
||||
|
||||
## Exercises
|
||||
|
||||
Once everyone was set up, we moved on to talk about why testing is important and the different options available to run them, before looking at the different types of tests available in Drupal 8. For each test type, I explained what it was used for and everyone completed an exercise on each - creating a test of that type, initially seeing it fail, and then doing the work to get it to pass.
|
||||
Once everyone was set up, we moved on to talk about why testing is important and
|
||||
the different options available to run them, before looking at the different
|
||||
types of tests available in Drupal 8. For each test type, I explained what it
|
||||
was used for and everyone completed an exercise on each - creating a test of
|
||||
that type, initially seeing it fail, and then doing the work to get it to pass.
|
||||
|
||||
The completed code that I wrote beforehand for these is available in their own [GitHub repository][8], including all of the tests as well as the implementation code.
|
||||
The completed code that I wrote beforehand for these is available in their own
|
||||
[GitHub repository][8], including all of the tests as well as the implementation
|
||||
code.
|
||||
|
||||
Once these exercises were completed, we looked at creating a blog page using test driven development - the example that I use in the [TDD - Test Driven Drupal talk][9], to give a more real-word scenario. It would have been good to have gone through this as an exercise too, if we’d have had more time.
|
||||
Once these exercises were completed, we looked at creating a blog page using
|
||||
test driven development - the example that I use in the [TDD - Test Driven
|
||||
Drupal talk][9], to give a more real-word scenario. It would have been good to
|
||||
have gone through this as an exercise too, if we’d have had more time.
|
||||
|
||||
## Wrap Up
|
||||
|
||||
To finish, I demonstrated the PHPUnit integration within PHPStorm (which is working with Docksal) and showed some of the tests that I wrote for the [Private Message Queue][10] and [System User][11] modules, to see how things like adding items to queues and processing them, ensuring that emails are sent, to the right users and contain the right data, can be tested, as well as some of the tests that we’ve written on my work project over the last few months.
|
||||
To finish, I demonstrated the PHPUnit integration within PHPStorm (which is
|
||||
working with Docksal) and showed some of the tests that I wrote for the [Private
|
||||
Message Queue][10] and [System User][11] modules, to see how things like adding
|
||||
items to queues and processing them, ensuring that emails are sent, to the right
|
||||
users and contain the right data, can be tested, as well as some of the tests
|
||||
that we’ve written on my work project over the last few months.
|
||||
|
||||
## Slides
|
||||
|
||||
I didn’t record this workshop, but I have exported the slides and embedded them below:
|
||||
I didn’t record this workshop, but I have exported the slides and embedded them
|
||||
below:
|
||||
|
||||
{% include 'speakerdeck' with {
|
||||
data: {
|
||||
|
@ -39,26 +74,34 @@ I didn’t record this workshop, but I have exported the slides and embedded the
|
|||
|
||||
## Thoughts
|
||||
|
||||
I was very happy with how my first workshop went, it was a great experience for me and it seemed that the attendees all learnt something and found it interesting.
|
||||
I was very happy with how my first workshop went, it was a great experience for
|
||||
me and it seemed that the attendees all learnt something and found it
|
||||
interesting.
|
||||
|
||||
A couple of people mentioned about providing handouts to refer the code examples whilst working on the exercises, rather than relying on the slides and avoiding the need to sometimes switch back and forth between slides. I’ve found that I can export the slide deck as PNGs or JPGs from Deckset, so I’ll definitely do that next time.
|
||||
A couple of people mentioned about providing handouts to refer the code examples
|
||||
whilst working on the exercises, rather than relying on the slides and avoiding
|
||||
the need to sometimes switch back and forth between slides. I’ve found that I
|
||||
can export the slide deck as PNGs or JPGs from Deckset, so I’ll definitely do
|
||||
that next time.
|
||||
|
||||
I’m giving the [Test Driven Drupal][9] talk at the [Drupal Dev Days conference][12] next week, and I’m hoping to give it again at other meetups and events in the UK. If you’d like me to do either at your meetup or event, [get in touch][13].
|
||||
I’m giving the [Test Driven Drupal][9] talk at the [Drupal Dev Days
|
||||
conference][12] next week, and I’m hoping to give it again at other meetups and
|
||||
events in the UK. If you’d like me to do either at your meetup or event, [get in
|
||||
touch][13].
|
||||
|
||||
[0]: https://github.com/opdavies/drupal-testing-workshop
|
||||
[1]: https://github.com/drupal-composer/drupal-project
|
||||
[2]: https://docksal.io
|
||||
[3]: {{site.companies['microserve'].url}}
|
||||
[4]: https://github.com/drupal-composer/drupal-project
|
||||
[5]: https://www.drupal.org/project/examples
|
||||
[6]: /articles/creating-a-custom-phpunit-command-for-docksal
|
||||
[7]: /articles/using-environment-variables-settings-docksal
|
||||
[8]: https://github.com/opdavies/drupal-testing-workshop-exercises
|
||||
[9]: /talks/tdd-test-driven-drupal
|
||||
[10]: https://www.drupal.org/project/private_message_queue
|
||||
[11]: https://www.drupal.org/project/system_user
|
||||
[12]: {{site.events.drupal_dev_days_18.url}}
|
||||
[13]: /contact
|
||||
[14]: {{site.events.drupal_bristol.url}}
|
||||
[15]: /test-driven-drupal
|
||||
[16]: https://groups.drupal.org/node/520891
|
||||
|
||||
[3]: {{site.companies['microserve'].url}} [4]:
|
||||
https://github.com/drupal-composer/drupal-project [5]:
|
||||
https://www.drupal.org/project/examples [6]:
|
||||
/articles/creating-a-custom-phpunit-command-for-docksal [7]:
|
||||
/articles/using-environment-variables-settings-docksal [8]:
|
||||
https://github.com/opdavies/drupal-testing-workshop-exercises [9]:
|
||||
/talks/tdd-test-driven-drupal [10]:
|
||||
https://www.drupal.org/project/private_message_queue [11]:
|
||||
https://www.drupal.org/project/system_user [12]:
|
||||
{{site.events.drupal_dev_days_18.url}} [13]: /contact [14]:
|
||||
{{site.events.drupal_bristol.url}} [15]: /test-driven-drupal [16]:
|
||||
https://groups.drupal.org/node/520891
|
||||
|
|
|
@ -4,17 +4,28 @@ date: 2016-12-30
|
|||
excerpt: I’ve released some new versions of the Drupal VM Generator.
|
||||
tags: ['drupal-vm-generator', releases]
|
||||
---
|
||||
|
||||
The main updates are:
|
||||
|
||||
- Fixed an `InvalidResponseException` that was thrown from within the `boolean_as_string` Twig filter from the opdavies/twig-extensions library when the `config:generate` command was run in non-interactive mode.
|
||||
- Adding a working test suite for the existing commands, using PhpUnit and Symfony’s Process component. This is now linked to [Travis CI][2], and the tests are run on each commit and pull request.
|
||||
- The version requirements have been changed to allow 2.7 versions of the used Symfony Components, as well as the 3.x versions. This was done to resolve a conflict when also installing Drush globally with Composer.
|
||||
- Fixed an `InvalidResponseException` that was thrown from within the
|
||||
`boolean_as_string` Twig filter from the opdavies/twig-extensions library when
|
||||
the `config:generate` command was run in non-interactive mode.
|
||||
- Adding a working test suite for the existing commands, using PhpUnit and
|
||||
Symfony’s Process component. This is now linked to [Travis CI][2], and the
|
||||
tests are run on each commit and pull request.
|
||||
- The version requirements have been changed to allow 2.7 versions of the used
|
||||
Symfony Components, as well as the 3.x versions. This was done to resolve a
|
||||
conflict when also installing Drush globally with Composer.
|
||||
|
||||
## Next Steps
|
||||
|
||||
Currently the project is based on Drupal VM 3.0.0 which is an outdated version ([4.1.0][3] was released today). Adding updates and supporting the newer versions is a high priority, as well as keeping in sync with new releases. This will be easier with the test suite in place.
|
||||
Currently the project is based on Drupal VM 3.0.0 which is an outdated version
|
||||
([4.1.0][3] was released today). Adding updates and supporting the newer
|
||||
versions is a high priority, as well as keeping in sync with new releases. This
|
||||
will be easier with the test suite in place.
|
||||
|
||||
My initial thoughts are that version 2.10.0 will support Drupal VM 4.0.0, and if needed, 2.11.0 will ship shortly afterwards and support Drupal VM 4.1.0.
|
||||
My initial thoughts are that version 2.10.0 will support Drupal VM 4.0.0, and if
|
||||
needed, 2.11.0 will ship shortly afterwards and support Drupal VM 4.1.0.
|
||||
|
||||
[0]: http://www.drupalvmgenerator.com
|
||||
[1]: https://github.com/opdavies/drupal-vm-generator/tree/master/tests/Command
|
||||
|
|
|
@ -3,28 +3,45 @@ title: DrupalCamp Bristol 2018 Statement
|
|||
date: 2018-01-30
|
||||
excerpt: Unfortunately, we won’t be running DrupalCamp Bristol this year.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupalcamp-bristol
|
||||
- drupal-planet
|
||||
- drupalcamp-bristol
|
||||
use:
|
||||
- posts
|
||||
- posts
|
||||
meta:
|
||||
image:
|
||||
url: /images/blog/drupalcamp-bristol-17-logo.jpg
|
||||
width: 228
|
||||
height: 448
|
||||
type: image/img
|
||||
image:
|
||||
url: /images/blog/drupalcamp-bristol-17-logo.jpg
|
||||
width: 228
|
||||
height: 448
|
||||
type: image/img
|
||||
---
|
||||
It’s with heavy hearts that we are announcing there won’t be a DrupalCamp Bristol 2018. The committee have looked at the amount of work required to put the camp on and the capacity we all have and the two numbers are irreconcilable.
|
||||
|
||||
Seeing Drupalists from all over the country and from overseas come to Bristol to share knowledge and ideas is something we take pride in. The past three camps have been fantastic, but as a trend we have left it later and later to organise.
|
||||
It’s with heavy hearts that we are announcing there won’t be a DrupalCamp
|
||||
Bristol 2018. The committee have looked at the amount of work required to put
|
||||
the camp on and the capacity we all have and the two numbers are irreconcilable.
|
||||
|
||||
This year is the latest we have left to organise and we believe this is because we are all a bit fatigued right now, so it seems like a good place to stop and take stock.
|
||||
Seeing Drupalists from all over the country and from overseas come to Bristol to
|
||||
share knowledge and ideas is something we take pride in. The past three camps
|
||||
have been fantastic, but as a trend we have left it later and later to organise.
|
||||
|
||||
In our washup of last year’s camp we spoke a lot about what DrupalCamp is and who it is for. Traditionally we have tried to get a good mix of speakers from within the Drupal community and from the wider tech community. This does mean we dilute the ‘Drupal’ aspect of the camp, but the benefits it brings in terms of bringing together different views gives the camp greater value in our eyes.
|
||||
This year is the latest we have left to organise and we believe this is because
|
||||
we are all a bit fatigued right now, so it seems like a good place to stop and
|
||||
take stock.
|
||||
|
||||
It’s because of this mix of talks and wider shifts in the community in ‘getting us off the island’ that we have been thinking about rebranding to reflect the mix of talks that the camp hosts. The fact is DrupalCamps don’t just cover Drupal anymore. There is Symfony, Composer, OOP principles, React, etc.
|
||||
In our washup of last year’s camp we spoke a lot about what DrupalCamp is and
|
||||
who it is for. Traditionally we have tried to get a good mix of speakers from
|
||||
within the Drupal community and from the wider tech community. This does mean we
|
||||
dilute the ‘Drupal’ aspect of the camp, but the benefits it brings in terms of
|
||||
bringing together different views gives the camp greater value in our eyes.
|
||||
|
||||
We’ll take the gap this year to reevaluate who DrupalCamp Bristol is for and where it fits into the schedule of excellent tech events that take place in Bristol through the year, and we look forward to seeing you in 2019, refreshed and more enthusiastic than ever!
|
||||
It’s because of this mix of talks and wider shifts in the community in ‘getting
|
||||
us off the island’ that we have been thinking about rebranding to reflect the
|
||||
mix of talks that the camp hosts. The fact is DrupalCamps don’t just cover
|
||||
Drupal anymore. There is Symfony, Composer, OOP principles, React, etc.
|
||||
|
||||
We’ll take the gap this year to reevaluate who DrupalCamp Bristol is for and
|
||||
where it fits into the schedule of excellent tech events that take place in
|
||||
Bristol through the year, and we look forward to seeing you in 2019, refreshed
|
||||
and more enthusiastic than ever!
|
||||
|
||||
The DrupalCamp Bristol organising committee
|
||||
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
---
|
||||
title: Speakers and sessions announced for DrupalCamp Bristol 2019
|
||||
date: 2019-05-31
|
||||
excerpt: DrupalCamp Bristol is returning next month, and the accepted speakers and sessions have just been announced.
|
||||
excerpt:
|
||||
DrupalCamp Bristol is returning next month, and the accepted speakers and
|
||||
sessions have just been announced.
|
||||
tags: [drupalcamp, drupalcamp-bristol, dcbristol]
|
||||
---
|
||||
|
||||
<p class="lead" markdown="1">DrupalCamp Bristol is returning next month for a one-day, single-track conference, and we have just finished announcing the accepted sessions and speakers. It includes a mixture of new and returning speakers, presenting sessions including **Drupal in a microservice architecture**, **Automate to manage repetitive tasks with Ansible** and **Doing good with Drupal**.</p>
|
||||
|
||||
Find out more about all of our sessions and speakers on [the DrupalCamp Bristol website][website], as well as view the schedule for the day.
|
||||
Find out more about all of our sessions and speakers on [the DrupalCamp Bristol
|
||||
website][website], as well as view the schedule for the day.
|
||||
|
||||
Also, at the time of writing, [early bird tickets are still available][tickets] for a few more days!
|
||||
Also, at the time of writing, [early bird tickets are still available][tickets]
|
||||
for a few more days!
|
||||
|
||||
In the meantime, the videos from the 2017 Camp are on [our YouTube channel][youtube], including the opening keynote from [Emma Karayiannis][emma]:
|
||||
In the meantime, the videos from the 2017 Camp are on [our YouTube
|
||||
channel][youtube], including the opening keynote from [Emma Karayiannis][emma]:
|
||||
|
||||
{% include 'video-embed' with {
|
||||
classes: 'video-full',
|
||||
|
|
|
@ -1,38 +1,58 @@
|
|||
---
|
||||
title: DrupalCamp Bristol 2017 - Early Bird Tickets, Call for Sessions, Sponsors
|
||||
date: 2017-05-15
|
||||
excerpt: In less than two months time, DrupalCamp Bristol will be back for our third year.
|
||||
excerpt:
|
||||
In less than two months time, DrupalCamp Bristol will be back for our third
|
||||
year.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- drupalcamp
|
||||
- drupalcamp-bristol
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- drupalcamp
|
||||
- drupalcamp-bristol
|
||||
meta:
|
||||
image:
|
||||
url: /assets/image/blog/drupalcamp-bristol-17-logo.jpg
|
||||
height: 228
|
||||
width: 448
|
||||
type: image/jpg
|
||||
image:
|
||||
url: /assets/image/blog/drupalcamp-bristol-17-logo.jpg
|
||||
height: 228
|
||||
width: 448
|
||||
type: image/jpg
|
||||
---
|
||||
|
||||
<p class="text-center" markdown="1">![DrupalCamp Bristol 2017 logo](/images/blog/drupalcamp-bristol-17-logo.jpg)</p>
|
||||
|
||||
In less than two months time, [DrupalCamp Bristol][0] will be back for our third year! (July seems to come around quicker each year). This is this year’s schedule and venues:
|
||||
In less than two months time, [DrupalCamp Bristol][0] will be back for our third
|
||||
year! (July seems to come around quicker each year). This is this year’s
|
||||
schedule and venues:
|
||||
|
||||
+ 30th June - CXO (Business) day - [Watershed][1]
|
||||
+ 1st July - Developer conference - [University of Bristol, School of Chemistry][2]
|
||||
+ 2nd July - Contribution sprints - Venue TBC
|
||||
- 30th June - CXO (Business) day - [Watershed][1]
|
||||
- 1st July - Developer conference - [University of Bristol, School of
|
||||
Chemistry][2]
|
||||
- 2nd July - Contribution sprints - Venue TBC
|
||||
|
||||
Today we announced [Emma Karayiannis][3] as our Saturday keynote speaker, and we’ll be announcing some of the other speakers later this week.
|
||||
Today we announced [Emma Karayiannis][3] as our Saturday keynote speaker, and
|
||||
we’ll be announcing some of the other speakers later this week.
|
||||
|
||||
Not submitted your session yet? The [session submissions][12] are open until May 31st. We’re looking for talks not only on Drupal, but other related topics such as PHP, Symfony, server administration/DevOps, project management, case studies, being human etc. If you want to submit but want to ask something beforehand, please [send us an email][4] or ping us on [Twitter][5].
|
||||
Not submitted your session yet? The [session submissions][12] are open until May
|
||||
31st. We’re looking for talks not only on Drupal, but other related topics such
|
||||
as PHP, Symfony, server administration/DevOps, project management, case studies,
|
||||
being human etc. If you want to submit but want to ask something beforehand,
|
||||
please [send us an email][4] or ping us on [Twitter][5].
|
||||
|
||||
Not spoken at a DrupalCamp before? No problem. We’re looking for both new and experienced speakers, and have both long (45 minutes) and short (20 minutes) talk slots available.
|
||||
Not spoken at a DrupalCamp before? No problem. We’re looking for both new and
|
||||
experienced speakers, and have both long (45 minutes) and short (20 minutes)
|
||||
talk slots available.
|
||||
|
||||
Not bought your tickets yet? [Early bird tickets][10] for the CXO and conference days are still available! The sprint day tickets are free but limited, so do register for a ticket to claim your place.
|
||||
Not bought your tickets yet? [Early bird tickets][10] for the CXO and conference
|
||||
days are still available! The sprint day tickets are free but limited, so do
|
||||
register for a ticket to claim your place.
|
||||
|
||||
We still have [sponsorships opportunities][6] available (big thanks to [Microserve][7], [Deeson][8] and [Proctors][9]) who have already signed up), but be quick if you want to be included in our brochure so that we can get you added before our print deadline! Without our sponsors, putting on this event each year would not be possible.
|
||||
We still have [sponsorships opportunities][6] available (big thanks to
|
||||
[Microserve][7], [Deeson][8] and [Proctors][9]) who have already signed up), but
|
||||
be quick if you want to be included in our brochure so that we can get you added
|
||||
before our print deadline! Without our sponsors, putting on this event each year
|
||||
would not be possible.
|
||||
|
||||
Any other questions? Take a look at [our website][0] or get in touch via [Twitter][5] or [email][11].
|
||||
Any other questions? Take a look at [our website][0] or get in touch via
|
||||
[Twitter][5] or [email][11].
|
||||
|
||||
[0]: https://2017.drupalcampbristol.co.uk
|
||||
[1]: http://www.watershed.co.uk
|
||||
|
@ -44,6 +64,7 @@ Any other questions? Take a look at [our website][0] or get in touch via [Twitte
|
|||
[7]: https://microserve.io
|
||||
[8]: https://www.deeson.co.uk
|
||||
[9]: http://www.proctors.co.uk
|
||||
[10]: https://www.eventbrite.co.uk/e/drupalcamp-bristol-2017-tickets-33574193316#ticket
|
||||
[10]:
|
||||
https://www.eventbrite.co.uk/e/drupalcamp-bristol-2017-tickets-33574193316#ticket
|
||||
[11]: mailto:info@drupalcampbristol.co.uk
|
||||
[12]: https://2017.drupalcampbristol.co.uk/#block-dcb2017-page-title
|
||||
|
|
|
@ -8,10 +8,17 @@ tags:
|
|||
- git
|
||||
- git-flow
|
||||
---
|
||||
It's all booked, I'm going to be attending [DrupalCamp London](http://2014.drupalcamplondon.co.uk) this year, my first DrupalCamp!
|
||||
|
||||
I'm going as a volunteer, so I'm going to be helping with the registrations on the Saturday morning and for another couple hours elsewhere over the weekend. I've also offered to help organise and oversee some code sprints, although I'm definitely wanting to do some sprinting of my own and attend a few sessions.
|
||||
It's all booked, I'm going to be attending
|
||||
[DrupalCamp London](http://2014.drupalcamplondon.co.uk) this year, my first
|
||||
DrupalCamp!
|
||||
|
||||
I'm looking forward to meeting some new people as well as catching up with some people that I met at [DrupalCon Prague](http://prague2013.drupal.org).
|
||||
I'm going as a volunteer, so I'm going to be helping with the registrations on
|
||||
the Saturday morning and for another couple hours elsewhere over the weekend.
|
||||
I've also offered to help organise and oversee some code sprints, although I'm
|
||||
definitely wanting to do some sprinting of my own and attend a few sessions.
|
||||
|
||||
I'm looking forward to meeting some new people as well as catching up with some
|
||||
people that I met at [DrupalCon Prague](http://prague2013.drupal.org).
|
||||
|
||||
If you're also coming, see you there!
|
||||
|
|
|
@ -1,30 +1,39 @@
|
|||
---
|
||||
title: DrupalCamp London 2019 - Tickets Available and Call for Sessions
|
||||
date: 2018-11-20
|
||||
excerpt: DrupalCamp London early-bird tickets are now available, and their call for sessions is open.
|
||||
excerpt:
|
||||
DrupalCamp London early-bird tickets are now available, and their call for
|
||||
sessions is open.
|
||||
tags:
|
||||
- conferences
|
||||
- drupal
|
||||
- drupalcamp
|
||||
- drupalcamp-london
|
||||
- conferences
|
||||
- drupal
|
||||
- drupalcamp
|
||||
- drupalcamp-london
|
||||
has_tweets: true
|
||||
---
|
||||
It was announced this week that [early-bird tickets are now available][0] for [DrupalCamp London 2019][1], as well as their [call for sessions being open][2].
|
||||
|
||||
It was announced this week that [early-bird tickets are now available][0] for
|
||||
[DrupalCamp London 2019][1], as well as their [call for sessions being open][2].
|
||||
|
||||
{% include 'tweet' with {
|
||||
content: '<p lang="en" dir="ltr">The time is finally here. You can now purchase your tickets. Early Bird finishes on 2nd January 2019 - <a href="https://t.co/aG6jstmWzv">https://t.co/aG6jstmWzv</a> <a href="https://twitter.com/hashtag/Drupal?src=hash&ref_src=twsrc%5Etfw">#Drupal</a></p>— DrupalCamp London (@DrupalCampLDN) <a href="https://twitter.com/DrupalCampLDN/status/1064584179113971712?ref_src=twsrc%5Etfw">November 19, 2018</a>
|
||||
',
|
||||
} %}
|
||||
|
||||
I’ve attended, given talks and volunteered previously, would definitely recommend others doing so, and I plan on attending and submitting again myself for 2019.
|
||||
If there’s something in particular that you’d like to see me give a talk on, let me know - I’d be happy to hear any suggestions.
|
||||
Alternatively, if you’d like to submit and would like some help writing an abstract or want some feedback on a talk idea, please get in touch.
|
||||
I’ve attended, given talks and volunteered previously, would definitely
|
||||
recommend others doing so, and I plan on attending and submitting again myself
|
||||
for 2019. If there’s something in particular that you’d like to see me give a
|
||||
talk on, let me know - I’d be happy to hear any suggestions. Alternatively, if
|
||||
you’d like to submit and would like some help writing an abstract or want some
|
||||
feedback on a talk idea, please get in touch.
|
||||
|
||||
_Note: I am not an organiser of DrupalCamp London, nor am I involved with the session selection process._
|
||||
_Note: I am not an organiser of DrupalCamp London, nor am I involved with the
|
||||
session selection process._
|
||||
|
||||
Hopefully there will be no [#uksnow][3] this year!
|
||||
|
||||
DrupalCamp London is the 1-3 March 2019. Early bird tickets are available until 2 January 2019, and the call for sessions is open until 21 January.
|
||||
DrupalCamp London is the 1-3 March 2019. Early bird tickets are available until
|
||||
2 January 2019, and the call for sessions is open until 21 January.
|
||||
|
||||
[0]: https://twitter.com/DrupalCampLDN/status/1064584179113971712
|
||||
[1]: https://drupalcamp.london
|
||||
|
|
|
@ -4,16 +4,23 @@ excerpt: This year, I’m teaching a workshop at DrupalCamp London.
|
|||
tags: [drupal, drupalcamp, testing]
|
||||
date: 2020-02-05
|
||||
lead_image:
|
||||
url: /images/blog/testing-workshop-drupalcamp-london/lead.jpg
|
||||
url: /images/blog/testing-workshop-drupalcamp-london/lead.jpg
|
||||
---
|
||||
|
||||
![]({{page.lead_image.url}}){.p-1 .border}
|
||||
|
||||
<p>{{ page.excerpt }}</p>
|
||||
|
||||
The subject will be automated testing and test driven development in Drupal 8, and it will be on Friday 13th March 2020, between 1pm and 5pm.
|
||||
The subject will be automated testing and test driven development in Drupal 8,
|
||||
and it will be on Friday 13th March 2020, between 1pm and 5pm.
|
||||
|
||||
In the workshop, I’ll cover the methodology, approaches and terminology involved with automated testing, look at some examples and work through some exercises, and then take a test driven development approach to creating a new Drupal module.
|
||||
In the workshop, I’ll cover the methodology, approaches and terminology involved
|
||||
with automated testing, look at some examples and work through some exercises,
|
||||
and then take a test driven development approach to creating a new Drupal
|
||||
module.
|
||||
|
||||
There are also other workshops on topics including Composer, Drupal Commerce, profiling, and chatbots.
|
||||
There are also other workshops on topics including Composer, Drupal Commerce,
|
||||
profiling, and chatbots.
|
||||
|
||||
For more information and to register, go to the [DrupalCamp London website](https://opdavi.es/dclondon20 'Find out more and register on the DrupalCamp London website').
|
||||
For more information and to register, go to the
|
||||
[DrupalCamp London website](https://opdavi.es/dclondon20 'Find out more and register on the DrupalCamp London website').
|
||||
|
|
|
@ -1,33 +1,54 @@
|
|||
---
|
||||
title: Easier Git Repository Cloning with insteadOf
|
||||
date: 2019-03-07
|
||||
excerpt: How to simplify 'git clone' commands by using the insteadOf configuration option within your .gitconfig file.
|
||||
excerpt:
|
||||
How to simplify 'git clone' commands by using the insteadOf configuration
|
||||
option within your .gitconfig file.
|
||||
tags: [git]
|
||||
---
|
||||
When working on client or open source projects, I clone a lot of [Git](https://git-scm.com) repositories - either from GitHub, GitLab, Bitbucket or Drupal.org.
|
||||
The standard `git clone` commands though provided by these sites can be quite verbose with long repository URLs and use a mixture of different protocols, and I’d regularly need to go back to each website and look up the necessary command every time.
|
||||
|
||||
For example, here is the command provided to clone Drupal’s [Override Node Options module](https://www.drupal.org/project/override_node_options):
|
||||
When working on client or open source projects, I clone a lot of
|
||||
[Git](https://git-scm.com) repositories - either from GitHub, GitLab, Bitbucket
|
||||
or Drupal.org. The standard `git clone` commands though provided by these sites
|
||||
can be quite verbose with long repository URLs and use a mixture of different
|
||||
protocols, and I’d regularly need to go back to each website and look up the
|
||||
necessary command every time.
|
||||
|
||||
For example, here is the command provided to clone Drupal’s
|
||||
[Override Node Options module](https://www.drupal.org/project/override_node_options):
|
||||
|
||||
```plain
|
||||
git clone --branch 8.x-2.x https://git.drupal.org/project/override_node_options.git
|
||||
```
|
||||
|
||||
We can though simplify the command to make it easier and quicker to type, using a Git configuration option called `insteadOf`.
|
||||
We can though simplify the command to make it easier and quicker to type, using
|
||||
a Git configuration option called `insteadOf`.
|
||||
|
||||
## What is insteadOf?
|
||||
|
||||
From the [Git documentation](https://git-scm.com/docs/git-config#git-config-urlltbasegtinsteadOf):
|
||||
From the
|
||||
[Git documentation](https://git-scm.com/docs/git-config#git-config-urlltbasegtinsteadOf):
|
||||
|
||||
> **url.[base].insteadOf:**
|
||||
>
|
||||
> Any URL that starts with this value will be rewritten to start, instead, with [base]. In cases where some site serves a large number of repositories, and serves them with multiple access methods, and some users need to use different access methods, this feature allows people to specify any of the equivalent URLs and have Git automatically rewrite the URL to the best alternative for the particular user, even for a never-before-seen repository on the site. When more than one insteadOf strings match a given URL, the longest match is used.
|
||||
> Any URL that starts with this value will be rewritten to start, instead, with
|
||||
> [base]. In cases where some site serves a large number of repositories, and
|
||||
> serves them with multiple access methods, and some users need to use different
|
||||
> access methods, this feature allows people to specify any of the equivalent
|
||||
> URLs and have Git automatically rewrite the URL to the best alternative for
|
||||
> the particular user, even for a never-before-seen repository on the site. When
|
||||
> more than one insteadOf strings match a given URL, the longest match is used.
|
||||
|
||||
Whilst examples are sparse, [it seems like](https://stackoverflow.com/questions/1722807/how-to-convert-git-urls-to-http-urls) insteadOf is used for resolving protocol issues with repository URLs. However, we can use it to simplify our clone commands, as mentioned above.
|
||||
Whilst examples are sparse,
|
||||
[it seems like](https://stackoverflow.com/questions/1722807/how-to-convert-git-urls-to-http-urls)
|
||||
insteadOf is used for resolving protocol issues with repository URLs. However,
|
||||
we can use it to simplify our clone commands, as mentioned above.
|
||||
|
||||
## Example: cloning Drupal contrib projects
|
||||
|
||||
When working on Drupal core, or on a module, theme or distribution, you need to have a cloned version of that repository to generate patch files from, and apply patches to.
|
||||
When working on Drupal core, or on a module, theme or distribution, you need to
|
||||
have a cloned version of that repository to generate patch files from, and apply
|
||||
patches to.
|
||||
|
||||
Again, here is the provided command to clone the Override Node Options module:
|
||||
|
||||
|
@ -35,7 +56,9 @@ Again, here is the provided command to clone the Override Node Options module:
|
|||
git clone --branch 8.x-2.x https://git.drupal.org/project/override_node_options.git
|
||||
```
|
||||
|
||||
At the time of writing, the Git repository URL follow this same format - `https://git.drupal.org/project/{name}.git` (also the `.git` file extension is optional).
|
||||
At the time of writing, the Git repository URL follow this same format -
|
||||
`https://git.drupal.org/project/{name}.git` (also the `.git` file extension is
|
||||
optional).
|
||||
|
||||
To shorten and simplify this, I can add this snippet to my `~/.gitconfig` file:
|
||||
|
||||
|
@ -45,12 +68,16 @@ To shorten and simplify this, I can add this snippet to my `~/.gitconfig` file:
|
|||
insteadOf = drupal:
|
||||
```
|
||||
|
||||
With that added, I can now instead run `git clone drupal:{name}` or `git clone do:{name}` to clone the repository, specifying the project’s machine name.
|
||||
With that added, I can now instead run `git clone drupal:{name}` or
|
||||
`git clone do:{name}` to clone the repository, specifying the project’s machine
|
||||
name.
|
||||
|
||||
For example, to clone the Override Node Options module, I can now do this using just `git clone drupal:override_node_options`.
|
||||
For example, to clone the Override Node Options module, I can now do this using
|
||||
just `git clone drupal:override_node_options`.
|
||||
|
||||
This, I think, is definitely quicker and easier!
|
||||
|
||||
## Resources
|
||||
|
||||
You can view my entire `.gitconfig` file, as well as my other dotfiles, in [my dotfiles repository on GitHub](https://github.com/opdavies/dotfiles/blob/master/.gitconfig).
|
||||
You can view my entire `.gitconfig` file, as well as my other dotfiles, in
|
||||
[my dotfiles repository on GitHub](https://github.com/opdavies/dotfiles/blob/master/.gitconfig).
|
||||
|
|
|
@ -1,14 +1,26 @@
|
|||
---
|
||||
title: Easier Sculpin Commands with Composer and NPM Scripts
|
||||
date: 2017-01-07
|
||||
excerpt: In this video, I show you how I've simplied my Sculpin and Gulp workflow using custom Composer and NPM scripts.
|
||||
excerpt:
|
||||
In this video, I show you how I've simplied my Sculpin and Gulp workflow using
|
||||
custom Composer and NPM scripts.
|
||||
tags: [composer, gulp, sculpin]
|
||||
---
|
||||
In this video, I show you how I've simplied my Sculpin and Gulp workflow using custom Composer and NPM scripts.
|
||||
|
||||
My website includes several various command line tools - e.g. [Sculpin][4], [Gulp][5] and [Behat][6] - each needing different arguments and options, depending on the command being run. For example, for Sculpin, I normally include several additional options when viewing the site locally - the full command that I use is `./vendor/bin/sculpin generate --watch --server --clean --no-interaction`. Typing this repeatedly is time consuming and could be easily mis-typed, forgotten or confused with other commands.
|
||||
In this video, I show you how I've simplied my Sculpin and Gulp workflow using
|
||||
custom Composer and NPM scripts.
|
||||
|
||||
In this video, I show you how I've simplied my Sculpin and Gulp workflow using custom Composer and NPM scripts.
|
||||
My website includes several various command line tools - e.g. [Sculpin][4],
|
||||
[Gulp][5] and [Behat][6] - each needing different arguments and options,
|
||||
depending on the command being run. For example, for Sculpin, I normally include
|
||||
several additional options when viewing the site locally - the full command that
|
||||
I use is
|
||||
`./vendor/bin/sculpin generate --watch --server --clean --no-interaction`.
|
||||
Typing this repeatedly is time consuming and could be easily mis-typed,
|
||||
forgotten or confused with other commands.
|
||||
|
||||
In this video, I show you how I've simplied my Sculpin and Gulp workflow using
|
||||
custom Composer and NPM scripts.
|
||||
|
||||
<div class="embed-container">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/eiWDV_63yCQ" frameborder="0" allowfullscreen></iframe>
|
||||
|
@ -16,7 +28,11 @@ In this video, I show you how I've simplied my Sculpin and Gulp workflow using c
|
|||
|
||||
## Scripts
|
||||
|
||||
Here are the scripts that I’m using - they are slightly different from those in the video. I use the `--generate` and `--watch` options for Sculpin and the `gulp watch` command for NPM. I had to change these before the recording as I was using the [demo magic][0] script to run the commands, and existing from a watch session was also ending the script process.
|
||||
Here are the scripts that I’m using - they are slightly different from those in
|
||||
the video. I use the `--generate` and `--watch` options for Sculpin and the
|
||||
`gulp watch` command for NPM. I had to change these before the recording as I
|
||||
was using the [demo magic][0] script to run the commands, and existing from a
|
||||
watch session was also ending the script process.
|
||||
|
||||
### composer.json
|
||||
|
||||
|
@ -42,7 +58,8 @@ Run with `composer run <name>`, e.g. `composer run dev`.
|
|||
|
||||
Run with `npm run <name>`, e.g. `npm run production`.
|
||||
|
||||
You can also take a look at the full [composer.json][1] and [package.json][2] files within my site repository on [GitHub][3].
|
||||
You can also take a look at the full [composer.json][1] and [package.json][2]
|
||||
files within my site repository on [GitHub][3].
|
||||
|
||||
## Resources
|
||||
|
||||
|
|
|
@ -1,20 +1,34 @@
|
|||
---
|
||||
title: Easily Embed TypeKit Fonts into your Drupal Website
|
||||
date: 2011-02-14
|
||||
excerpt: How to use the @font-your-face module to embed TypeKit fonts into your Drupal website.
|
||||
excerpt:
|
||||
How to use the @font-your-face module to embed TypeKit fonts into your Drupal
|
||||
website.
|
||||
tags:
|
||||
- drupal-planet
|
||||
- drupal-6
|
||||
- typekit
|
||||
---
|
||||
To begin with, you will need to [register for a TypeKit account](https://typekit.com/plans) - there is a free version if you just want to try it out.
|
||||
|
||||
Next, you'll need to create a kit that contains the fonts that you want to use on your website. I've used [FF Tisa Web Pro](http://typekit.com/fonts/ff-tisa-web-pro).
|
||||
To begin with, you will need to
|
||||
[register for a TypeKit account](https://typekit.com/plans) - there is a free
|
||||
version if you just want to try it out.
|
||||
|
||||
Under 'Kit Settings', ensure that your website domain (e.g. mysite.com) is listed under 'Domains'.
|
||||
Next, you'll need to create a kit that contains the fonts that you want to use
|
||||
on your website. I've used
|
||||
[FF Tisa Web Pro](http://typekit.com/fonts/ff-tisa-web-pro).
|
||||
|
||||
Download and install the [@font-your-face](http://drupal.org/project/fontyourface) module onto your Drupal site, and to go admin/settings/fontyourface to configure it. Enter [your TypeKit API key](https://typekit.com/account/tokens), and click 'Import Typekit' to import your kits and fonts.
|
||||
Under 'Kit Settings', ensure that your website domain (e.g. mysite.com) is
|
||||
listed under 'Domains'.
|
||||
|
||||
Go to admin/dist/themes/fontyourface, and click 'Browse fonts to enable'. Click on the name of the font that you want to enable, check 'Enabled', and click 'Edit font' to save your changes.
|
||||
Download and install the
|
||||
[@font-your-face](http://drupal.org/project/fontyourface) module onto your
|
||||
Drupal site, and to go admin/settings/fontyourface to configure it. Enter
|
||||
[your TypeKit API key](https://typekit.com/account/tokens), and click 'Import
|
||||
Typekit' to import your kits and fonts.
|
||||
|
||||
Go to admin/dist/themes/fontyourface, and click 'Browse fonts to enable'. Click
|
||||
on the name of the font that you want to enable, check 'Enabled', and click
|
||||
'Edit font' to save your changes.
|
||||
|
||||
With the font enabled, you can now use it in your CSS.
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
---
|
||||
title: Programmatically Load an Entityform in Drupal 7
|
||||
date: 2015-12-22
|
||||
excerpt: How to programmatically load, render and embed an entityform in Drupal 7.
|
||||
excerpt:
|
||||
How to programmatically load, render and embed an entityform in Drupal 7.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-7
|
||||
- drupal-planet
|
||||
- entityform
|
||||
- drupal
|
||||
- drupal-7
|
||||
- drupal-planet
|
||||
- entityform
|
||||
---
|
||||
I recently had my first experience using the [Entityform module](https://www.drupal.org/project/entityform) in a project. It was quite easy to configure with different form types, but then I needed to embed the form into an overlay. I was expecting to use the `drupal_get_form()` function and render it, but this didn’t work.
|
||||
|
||||
I recently had my first experience using the
|
||||
[Entityform module](https://www.drupal.org/project/entityform) in a project. It
|
||||
was quite easy to configure with different form types, but then I needed to
|
||||
embed the form into an overlay. I was expecting to use the `drupal_get_form()`
|
||||
function and render it, but this didn’t work.
|
||||
|
||||
Here are the steps that I took to be able to load, render and embed the form.
|
||||
|
||||
## Loading the Form
|
||||
|
||||
The first thing that I needed to do to render the form was to load an empty instance of the entityform using `entityform_empty_load()`. In this example, `newsletter` is the name of my form type.
|
||||
The first thing that I needed to do to render the form was to load an empty
|
||||
instance of the entityform using `entityform_empty_load()`. In this example,
|
||||
`newsletter` is the name of my form type.
|
||||
|
||||
```language-php
|
||||
$form = entityform_empty_load('newsletter');
|
||||
|
@ -24,9 +32,12 @@ This returns an instance of a relevant `Entityform` object.
|
|||
|
||||
## Rendering the Form
|
||||
|
||||
The next step was to be able to render the form. I did this using the `entity_form_wrapper()` function.
|
||||
The next step was to be able to render the form. I did this using the
|
||||
`entity_form_wrapper()` function.
|
||||
|
||||
As this function is within the `entityform.admin.inc` file and not autoloaded by Drupal, I needed to include it using `module_load_include()` so that the function was available.
|
||||
As this function is within the `entityform.admin.inc` file and not autoloaded by
|
||||
Drupal, I needed to include it using `module_load_include()` so that the
|
||||
function was available.
|
||||
|
||||
```language-php
|
||||
module_load_include('inc', 'entityform', 'entityform.admin');
|
||||
|
@ -34,13 +45,19 @@ module_load_include('inc', 'entityform', 'entityform.admin');
|
|||
$output = entityform_form_wrapper($form, 'submit', 'embedded'),
|
||||
```
|
||||
|
||||
The first argument is the `Entityform` object that was created in the previous step (I’ve [submitted a patch](https://www.drupal.org/node/2639584) to type hint this within entityform so that it’s clearer what is expected), which is required.
|
||||
The first argument is the `Entityform` object that was created in the previous
|
||||
step (I’ve [submitted a patch](https://www.drupal.org/node/2639584) to type hint
|
||||
this within entityform so that it’s clearer what is expected), which is
|
||||
required.
|
||||
|
||||
The other two arguments are optional. The second argument is the mode (`submit` is the default value), and the last is the form context. `page` is the default value, for use on the submit page, however I changed this to `embedded`.
|
||||
The other two arguments are optional. The second argument is the mode (`submit`
|
||||
is the default value), and the last is the form context. `page` is the default
|
||||
value, for use on the submit page, however I changed this to `embedded`.
|
||||
|
||||
I could then pass this result into my theme function to render it successfully within the relevant template file.
|
||||
I could then pass this result into my theme function to render it successfully
|
||||
within the relevant template file.
|
||||
|
||||
## Resources
|
||||
|
||||
* [The entityform module](https://www.drupal.org/project/entityform)
|
||||
* [My issue and patch to add the type hint to the entityform_form_wrapper function](https://www.drupal.org/node/2639584)
|
||||
- [The entityform module](https://www.drupal.org/project/entityform)
|
||||
- [My issue and patch to add the type hint to the entityform_form_wrapper function](https://www.drupal.org/node/2639584)
|
||||
|
|
|
@ -1,24 +1,35 @@
|
|||
---
|
||||
title: Examples of using Laravel Collections in Drupal
|
||||
date: 2018-08-23
|
||||
excerpt: Some examples of using Laravel’s Illuminate Collections within Drupal projects.
|
||||
excerpt:
|
||||
Some examples of using Laravel’s Illuminate Collections within Drupal
|
||||
projects.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-7
|
||||
- drupal-8
|
||||
- drupal-planet
|
||||
- laravel
|
||||
- laravel-collections
|
||||
- php
|
||||
- drupal
|
||||
- drupal-7
|
||||
- drupal-8
|
||||
- drupal-planet
|
||||
- laravel
|
||||
- laravel-collections
|
||||
- php
|
||||
has_tweets: true
|
||||
---
|
||||
Since starting to work with Laravel as well as Drupal and Symfony, watching Adam Wathan’s [Refactoring to Collections][0] course as well as [lessons on Laracasts][6], I’ve become a fan of [Laravel’s Illuminate Collections][1] and the object-orientated pipeline approach for interacting with PHP arrays.
|
||||
|
||||
In fact I’ve given a talk on [using Collections outside Laravel][2] and have written a [Collection class module][3] for Drupal 7.
|
||||
Since starting to work with Laravel as well as Drupal and Symfony, watching Adam
|
||||
Wathan’s [Refactoring to Collections][0] course as well as [lessons on
|
||||
Laracasts][6], I’ve become a fan of [Laravel’s Illuminate Collections][1] and
|
||||
the object-orientated pipeline approach for interacting with PHP arrays.
|
||||
|
||||
I’ve also tweeted several examples of code that I’ve written within Drupal that use Collections, and I thought it would be good to collate them all here for reference.
|
||||
In fact I’ve given a talk on [using Collections outside Laravel][2] and have
|
||||
written a [Collection class module][3] for Drupal 7.
|
||||
|
||||
Thanks again to [Tighten][4] for releasing and maintaining the [tightenco/collect library][5] that makes it possible to pull in Collections via Composer.
|
||||
I’ve also tweeted several examples of code that I’ve written within Drupal that
|
||||
use Collections, and I thought it would be good to collate them all here for
|
||||
reference.
|
||||
|
||||
Thanks again to [Tighten][4] for releasing and maintaining the
|
||||
[tightenco/collect library][5] that makes it possible to pull in Collections via
|
||||
Composer.
|
||||
|
||||
<div class="lg:flex lg:flex-wrap lg:-mx-4">
|
||||
{% include 'tweet' with {
|
||||
|
@ -50,6 +61,7 @@ Thanks again to [Tighten][4] for releasing and maintaining the [tightenco/collec
|
|||
data_cards: true,
|
||||
content: '<p lang="en" dir="ltr">Some more <a href="https://twitter.com/hashtag/Drupal?src=hash&ref_src=twsrc%5Etfw">#Drupal</a> 8 fun with Laravel Collections. Loading the tags for a post and generating a formatted string of tweetable hashtags. <a href="https://t.co/GbyiRPzIRo">pic.twitter.com/GbyiRPzIRo</a></p>— Oliver Davies (@opdavies) <a href="https://twitter.com/opdavies/status/1032544228029673472?ref_src=twsrc%5Etfw">August 23, 2018</a>',
|
||||
} %}
|
||||
|
||||
</div>
|
||||
|
||||
[0]: https://adamwathan.me/refactoring-to-collections
|
||||
|
|
|
@ -1,26 +1,39 @@
|
|||
---
|
||||
title: Experimenting with events in Drupal 8
|
||||
date: 2018-08-21
|
||||
excerpt: Trying a different way of structuring Drupal modules, using event subscribers and autowiring.
|
||||
excerpt:
|
||||
Trying a different way of structuring Drupal modules, using event subscribers
|
||||
and autowiring.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-planet
|
||||
- php
|
||||
- symfony
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-planet
|
||||
- php
|
||||
- symfony
|
||||
promoted: true
|
||||
---
|
||||
I’ve been experimenting with moving some code to Drupal 8, and I’m quite intrigued by a different way that I’ve tried to structure it - using event subscribers, building on some of the takeaways from Drupal Dev Days.
|
||||
|
||||
I’ve been experimenting with moving some code to Drupal 8, and I’m quite
|
||||
intrigued by a different way that I’ve tried to structure it - using event
|
||||
subscribers, building on some of the takeaways from Drupal Dev Days.
|
||||
|
||||
Here is how this module is currently structured:
|
||||
|
||||
![](/images/blog/events-drupal-8/1.png){.border .p-1}
|
||||
|
||||
Note that there is no `opdavies_blog.module` file, and rather than calling actions from within a hook like `opdavies_blog_entity_update()`, each action becomes it’s own event subscriber class.
|
||||
Note that there is no `opdavies_blog.module` file, and rather than calling
|
||||
actions from within a hook like `opdavies_blog_entity_update()`, each action
|
||||
becomes it’s own event subscriber class.
|
||||
|
||||
This means that there are no long `hook_entity_update` functions, and instead there are descriptive, readable event subscriber class names, simpler action code that is responsibile only for performing one task, and you’re able to inject and autowire dependencies into the event subscriber classes as services - making it easier and cleaner to use dependency injection, and simpler write tests to mock dependencies when needed.
|
||||
This means that there are no long `hook_entity_update` functions, and instead
|
||||
there are descriptive, readable event subscriber class names, simpler action
|
||||
code that is responsibile only for performing one task, and you’re able to
|
||||
inject and autowire dependencies into the event subscriber classes as services -
|
||||
making it easier and cleaner to use dependency injection, and simpler write
|
||||
tests to mock dependencies when needed.
|
||||
|
||||
The additional events are provided by the [Hook Event Dispatcher module](https://www.drupal.org/project/hook_event_dispatcher).
|
||||
The additional events are provided by the
|
||||
[Hook Event Dispatcher module](https://www.drupal.org/project/hook_event_dispatcher).
|
||||
|
||||
## Code
|
||||
|
||||
|
|
|
@ -1,16 +1,28 @@
|
|||
---
|
||||
title: How to fix Vagrant Loading the Wrong Virtual Machine
|
||||
date: 2014-10-06
|
||||
excerpt: Here are the steps that I took to fix Vagrant and point it back at the correct VM.
|
||||
excerpt:
|
||||
Here are the steps that I took to fix Vagrant and point it back at the correct
|
||||
VM.
|
||||
tags:
|
||||
- vagrant
|
||||
- virtualbox
|
||||
---
|
||||
A few times recently, I've had instances where [Vagrant](https://www.vagrantup.com) seems to have forgotten which virtual machine it's supposed to load, probably due to renaming a project directory or the .vagrant directory being moved accidentally.
|
||||
|
||||
Here are the steps that I took to fix this and point Vagrant back at the correct VM.
|
||||
A few times recently, I've had instances where
|
||||
[Vagrant](https://www.vagrantup.com) seems to have forgotten which virtual
|
||||
machine it's supposed to load, probably due to renaming a project directory or
|
||||
the .vagrant directory being moved accidentally.
|
||||
|
||||
Here are the steps that I took to fix this and point Vagrant back at the correct
|
||||
VM.
|
||||
|
||||
1. Stop the machine from running using the `$ vagrant halt` command.
|
||||
1. Use the `$ VBoxManage list vms` command to view a list of the virtual machines on your system. Note the ID of the correct VM that should be loading. For example, `"foo_default_1405481857614_74478" {e492bfc3-cac2-4cde-a396-e81e37e421e2}`. The number within the curly brackets is the ID of the virtual machine.
|
||||
1. Within the .vagrant directory in your project (it is hidden by default), update the ID within the machines/default/virtualbox/id file.
|
||||
1. Use the `$ VBoxManage list vms` command to view a list of the virtual
|
||||
machines on your system. Note the ID of the correct VM that should be
|
||||
loading. For example,
|
||||
`"foo_default_1405481857614_74478" {e492bfc3-cac2-4cde-a396-e81e37e421e2}`.
|
||||
The number within the curly brackets is the ID of the virtual machine.
|
||||
1. Within the .vagrant directory in your project (it is hidden by default),
|
||||
update the ID within the machines/default/virtualbox/id file.
|
||||
1. Start the new VM with `$ vagrant up`.
|
||||
|
|
|
@ -1,21 +1,33 @@
|
|||
---
|
||||
title: Fixing Drupal SimpleTest issues inside Docker Containers
|
||||
date: 2017-05-05
|
||||
excerpt: How I managed to get my Drupal SimpleTest tests to run and pass within Docker containers.
|
||||
excerpt:
|
||||
How I managed to get my Drupal SimpleTest tests to run and pass within Docker
|
||||
containers.
|
||||
tags:
|
||||
- docker
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- simpletest
|
||||
- testing
|
||||
- docker
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- simpletest
|
||||
- testing
|
||||
---
|
||||
I’ve been a Drupal VM user for a long time, but lately I’ve been using a combination Drupal VM and Docker for my local development environment. There were a couple of issues preventing me from completely switching to Docker - one of which being that when I tried running of my Simpletest tests, a lot of them would fail where they would pass when run within Drupal VM.
|
||||
|
||||
I’ve been a Drupal VM user for a long time, but lately I’ve been using a
|
||||
combination Drupal VM and Docker for my local development environment. There
|
||||
were a couple of issues preventing me from completely switching to Docker - one
|
||||
of which being that when I tried running of my Simpletest tests, a lot of them
|
||||
would fail where they would pass when run within Drupal VM.
|
||||
|
||||
Here’s an excerpt from my `docker-compose.yml` file:
|
||||
|
||||
**TL;DR** You need to include the name of your web server container as the `--url` option to `run-scripts.php`.
|
||||
**TL;DR** You need to include the name of your web server container as the
|
||||
`--url` option to `run-scripts.php`.
|
||||
|
||||
I’ve been a [Drupal VM][1] user for a long time, but lately I’ve been using a combination Drupal VM and [Docker][0] for my local development environment. There were a couple of issues preventing me from completely switching to Docker - one of which being that when I tried running of my Simpletest tests, a lot of them would fail where they would pass when run within Drupal VM.
|
||||
I’ve been a [Drupal VM][1] user for a long time, but lately I’ve been using a
|
||||
combination Drupal VM and [Docker][0] for my local development environment.
|
||||
There were a couple of issues preventing me from completely switching to
|
||||
Docker - one of which being that when I tried running of my Simpletest tests, a
|
||||
lot of them would fail where they would pass when run within Drupal VM.
|
||||
|
||||
Here’s an excerpt from my `docker-compose.yml` file:
|
||||
|
||||
|
@ -38,7 +50,8 @@ services:
|
|||
...
|
||||
```
|
||||
|
||||
Nginx and PHP-FPM are running in separate containers, the volumes are shared across both and the Nginx backend is set to use the `php` container.
|
||||
Nginx and PHP-FPM are running in separate containers, the volumes are shared
|
||||
across both and the Nginx backend is set to use the `php` container.
|
||||
|
||||
This is the command that I was using to run the tests:
|
||||
|
||||
|
@ -51,9 +64,14 @@ $ docker-compose run --rm \
|
|||
--class OverrideNodeOptionsTestCase
|
||||
```
|
||||
|
||||
This creates a new instance of the `php` container, sets the working directory to my Drupal root and runs Drupal’s `run-tests.sh` script with some arguments. In this case, I'm running the `OverrideNodeOptionsTestCase` class for the override_node_options tests. Once complete, the container is deleted because of the `--rm` option.
|
||||
This creates a new instance of the `php` container, sets the working directory
|
||||
to my Drupal root and runs Drupal’s `run-tests.sh` script with some arguments.
|
||||
In this case, I'm running the `OverrideNodeOptionsTestCase` class for the
|
||||
override_node_options tests. Once complete, the container is deleted because of
|
||||
the `--rm` option.
|
||||
|
||||
This resulted in 60 of the 112 tests failing, whereas they all passed when run within a Drupal VM instance.
|
||||
This resulted in 60 of the 112 tests failing, whereas they all passed when run
|
||||
within a Drupal VM instance.
|
||||
|
||||
```language-markup
|
||||
Test summary
|
||||
|
@ -64,16 +82,20 @@ Override node options 62 passes, 60 fails, 29 exceptions, and 17 debug messages
|
|||
Test run duration: 2 min 25 sec
|
||||
```
|
||||
|
||||
Running the tests again with the`--verbose` option, I saw this message appear in the output below some of the failing tests:
|
||||
Running the tests again with the`--verbose` option, I saw this message appear in
|
||||
the output below some of the failing tests:
|
||||
|
||||
> simplexml_import_dom(): Invalid Nodetype to import
|
||||
|
||||
**Up
|
||||
After checking that I had all of the required PHP extensions installed, I ran `docker-compose exec php bash` to connect to the `php` container and ran `curl http://localhost` to check the output. Rather than seeing the HTML for the site, I got this error message:
|
||||
\*\*Up After checking that I had all of the required PHP extensions installed, I
|
||||
ran `docker-compose exec php bash` to connect to the `php` container and ran
|
||||
`curl http://localhost` to check the output. Rather than seeing the HTML for the
|
||||
site, I got this error message:
|
||||
|
||||
> curl: (7) Failed to connect to localhost port 80: Connection refused
|
||||
|
||||
Whereas `curl http://nginx` returns the HTML for the page, so included it with the `--url` option to `run-tests.sh`, and this resulted in my tests all passing.
|
||||
Whereas `curl http://nginx` returns the HTML for the page, so included it with
|
||||
the `--url` option to `run-tests.sh`, and this resulted in my tests all passing.
|
||||
|
||||
```language-bash
|
||||
$ docker-compose run --rm \
|
||||
|
@ -94,9 +116,16 @@ Override node options 121 passes, 0 fails, 0 exceptions, and 34 debug messages
|
|||
Test run duration: 2 min 31 sec
|
||||
```
|
||||
|
||||
**Note:** In this example I have separate `nginx` and `php` containers, but I've tried and had the same issue when running Nginx and PHP-FPM in the same container - e.g. called `app` - and still needed to add `--url http://app` in order for the tests to run successfully.
|
||||
**Note:** In this example I have separate `nginx` and `php` containers, but I've
|
||||
tried and had the same issue when running Nginx and PHP-FPM in the same
|
||||
container - e.g. called `app` - and still needed to add `--url http://app` in
|
||||
order for the tests to run successfully.
|
||||
|
||||
I don’t know if this issue is macOS specfic (I know that [Drupal CI][2] is based on Docker, and I don’t know if it’s an issue) but I’m going to test also on my Ubuntu Desktop environment and investigate further and also compare the test run times for Docker in macOS, Docker in Ubuntu and within Drupal VM. I’m also going to test this with PHPUnit tests with Drupal 8.
|
||||
I don’t know if this issue is macOS specfic (I know that [Drupal CI][2] is based
|
||||
on Docker, and I don’t know if it’s an issue) but I’m going to test also on my
|
||||
Ubuntu Desktop environment and investigate further and also compare the test run
|
||||
times for Docker in macOS, Docker in Ubuntu and within Drupal VM. I’m also going
|
||||
to test this with PHPUnit tests with Drupal 8.
|
||||
|
||||
[0]: https://www.docker.com
|
||||
[1]: https://www.drupalvm.com
|
||||
|
|
|
@ -9,6 +9,7 @@ tags:
|
|||
- apache
|
||||
- mod_rewrite
|
||||
---
|
||||
|
||||
How to use the .htaccess file to forward to a different domain.
|
||||
|
||||
Within the mod_rewrite section of your .htaccess file, add the following lines:
|
||||
|
@ -18,7 +19,8 @@ RewriteCond %{HTTP_HOST} ^yoursite\.co\.uk$
|
|||
RewriteRule (.*) http://yoursite.com/$1 [R=301,L]
|
||||
```
|
||||
|
||||
This automatically forwards any users from http://yoursite.co.uk to http://yoursite.com. This can also be used to forward multiple domains:
|
||||
This automatically forwards any users from http://yoursite.co.uk to
|
||||
http://yoursite.com. This can also be used to forward multiple domains:
|
||||
|
||||
```language-apacheconf
|
||||
RewriteCond %{HTTP_HOST} ^yoursite\.co\.uk$ [OR]
|
||||
|
|
|
@ -1,22 +1,33 @@
|
|||
---
|
||||
title: git format-patch is your Friend
|
||||
date: 2014-05-21
|
||||
excerpt: An explanation of the "git format-patch" command, and how it could be used in Drupal's Git workflow.
|
||||
excerpt:
|
||||
An explanation of the "git format-patch" command, and how it could be used in
|
||||
Drupal's Git workflow.
|
||||
tags:
|
||||
- patches
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- git
|
||||
---
|
||||
An explanation of the "git format-patch" command, and how it could be used in Drupal's Git workflow.
|
||||
|
||||
An explanation of the "git format-patch" command, and how it could be used in
|
||||
Drupal's Git workflow.
|
||||
|
||||
## The Problem
|
||||
|
||||
As an active contributor to the [Drupal](http://drupal.org) project, I spend a lot of time working with other peoples’ modules and themes, and occassionally have to fix a bug or add some new functionality.
|
||||
As an active contributor to the [Drupal](http://drupal.org) project, I spend a
|
||||
lot of time working with other peoples’ modules and themes, and occassionally
|
||||
have to fix a bug or add some new functionality.
|
||||
|
||||
In the Drupal community, we use a patch based workflow where any changes that I make get exported to a file detailing the differences. The patch file (*.patch) is attached to an item in an issue queue on Drupal.org, applied by the maintainer to their local copy of the code and reviewed, and hopefully committed.
|
||||
In the Drupal community, we use a patch based workflow where any changes that I
|
||||
make get exported to a file detailing the differences. The patch file (\*.patch)
|
||||
is attached to an item in an issue queue on Drupal.org, applied by the
|
||||
maintainer to their local copy of the code and reviewed, and hopefully
|
||||
committed.
|
||||
|
||||
There is an option that the maintainer can add to the end of their commit message.
|
||||
There is an option that the maintainer can add to the end of their commit
|
||||
message.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -24,23 +35,33 @@ For example:
|
|||
--author="opdavies <opdavies@381388.no-reply.drupal.org>"
|
||||
```
|
||||
|
||||
This differs slightly different for each Drupal user, and the code can be found on their Drupal.org profile page.
|
||||
This differs slightly different for each Drupal user, and the code can be found
|
||||
on their Drupal.org profile page.
|
||||
|
||||
If this is added to the end of the commit message, the resulting commit will show that it was committed by the maintainer but authored by a different user. This will then display on Drupal.org that you’ve made a commit to that project.
|
||||
If this is added to the end of the commit message, the resulting commit will
|
||||
show that it was committed by the maintainer but authored by a different user.
|
||||
This will then display on Drupal.org that you’ve made a commit to that project.
|
||||
|
||||
![A screenshot of a commit that was authored by rli but committed by opdavies](/images/blog/git-format-patch.png)
|
||||
|
||||
The problem is that some project maintainers either don’t know about this option or occasionally forget to add it. [Dreditor](http://dreditor.org) can suggest a commit message and assign an author, but it is optional and, of course, not all maintainers use Dreditor (although they probably should).
|
||||
The problem is that some project maintainers either don’t know about this option
|
||||
or occasionally forget to add it. [Dreditor](http://dreditor.org) can suggest a
|
||||
commit message and assign an author, but it is optional and, of course, not all
|
||||
maintainers use Dreditor (although they probably should).
|
||||
|
||||
The `git format-patch` command seems to be the answer, and will be my preferred method for generating patch files in the future rather than `git diff`.
|
||||
The `git format-patch` command seems to be the answer, and will be my preferred
|
||||
method for generating patch files in the future rather than `git diff`.
|
||||
|
||||
## What does it do Differently?
|
||||
|
||||
From the [manual page](http://git-scm.com/docs/git-format-patch):
|
||||
|
||||
> Prepare each commit with its patch in one file per commit, formatted to resemble UNIX mailbox format. The output of this command is convenient for e-mail submission or for use with git am.
|
||||
> Prepare each commit with its patch in one file per commit, formatted to
|
||||
> resemble UNIX mailbox format. The output of this command is convenient for
|
||||
> e-mail submission or for use with git am.
|
||||
|
||||
Here is a section of a patch that I created for the [Metatag module](http://drupal.org/project/metatag) using `git format-patch`:
|
||||
Here is a section of a patch that I created for the
|
||||
[Metatag module](http://drupal.org/project/metatag) using `git format-patch`:
|
||||
|
||||
```language-bash
|
||||
From 80c8fa14de7f4a83c2e70367aab0aedcadf4f3b0 Mon Sep 17 00:00:00 2001
|
||||
|
@ -50,30 +71,50 @@ Subject: [PATCH] Exclude comment entities when checking if this is the page,
|
|||
---
|
||||
```
|
||||
|
||||
As mentioned above, the patch is structured in an email format. The commit message is used as the subject line, and the date that the commit was made locally is used for the date. What we’re interested in is the “From” value. This contains your name and email address from your `~/.gitconfig` file and is used to author the patch automatically.
|
||||
As mentioned above, the patch is structured in an email format. The commit
|
||||
message is used as the subject line, and the date that the commit was made
|
||||
locally is used for the date. What we’re interested in is the “From” value. This
|
||||
contains your name and email address from your `~/.gitconfig` file and is used
|
||||
to author the patch automatically.
|
||||
|
||||
Everything below this is the same as a standard patch file, the same as if was generated with `git diff`.
|
||||
Everything below this is the same as a standard patch file, the same as if was
|
||||
generated with `git diff`.
|
||||
|
||||
The full patch file can be found at <https://drupal.org/files/issues/metatag-comment-fragment-conflict-2265447-4.patch>.
|
||||
The full patch file can be found at
|
||||
<https://drupal.org/files/issues/metatag-comment-fragment-conflict-2265447-4.patch>.
|
||||
|
||||
## The Process
|
||||
|
||||
How did I create this patch? Here are the steps that I took:
|
||||
|
||||
1. Clone the source repository using `$ git clone --branch 7.x-1.x http://git.drupal.org/project/metatag.git` and move into that directory.
|
||||
2. Create a branch for this patch using `$ git checkout -b 2265447-comment-fragment-conflict`.
|
||||
1. Clone the source repository using
|
||||
`$ git clone --branch 7.x-1.x http://git.drupal.org/project/metatag.git` and
|
||||
move into that directory.
|
||||
2. Create a branch for this patch using
|
||||
`$ git checkout -b 2265447-comment-fragment-conflict`.
|
||||
3. Add and commit any changes as normal.
|
||||
4. Generate the patch file using `$ git format-patch 7.x-1.x --stdout > metatag-comment-fragment-conflict-2265447-4.patch`.
|
||||
4. Generate the patch file using
|
||||
`$ git format-patch 7.x-1.x --stdout > metatag-comment-fragment-conflict-2265447-4.patch`.
|
||||
|
||||
*Note:* I am defining 7.x-1.x in the last step as the original branch to compare (i.e. the original branch that we forked to make our issue branch). This will change depending on the project that you are patching, and it’s version number. Also, commits should always be made against the development branch and not the stable release.
|
||||
_Note:_ I am defining 7.x-1.x in the last step as the original branch to compare
|
||||
(i.e. the original branch that we forked to make our issue branch). This will
|
||||
change depending on the project that you are patching, and it’s version number.
|
||||
Also, commits should always be made against the development branch and not the
|
||||
stable release.
|
||||
|
||||
By default, a separate patch file will be created for each commit that we’ve made. This is overridden by the `--stdout` option which combines all of the patches into a single file. This is the recommended approach when uploading to Drupal.org.
|
||||
By default, a separate patch file will be created for each commit that we’ve
|
||||
made. This is overridden by the `--stdout` option which combines all of the
|
||||
patches into a single file. This is the recommended approach when uploading to
|
||||
Drupal.org.
|
||||
|
||||
The resulting patch file can be uploaded onto a Drupal.org issue queue, reviewed by the Testbot and applied by a module maintainer, and you automatically get the commit attributed. Problem solved.
|
||||
The resulting patch file can be uploaded onto a Drupal.org issue queue, reviewed
|
||||
by the Testbot and applied by a module maintainer, and you automatically get the
|
||||
commit attributed. Problem solved.
|
||||
|
||||
## Committing the Patch
|
||||
|
||||
If you need to commit a patch that was created using `git format-patch`, the best command to do this with is the `git am` command.
|
||||
If you need to commit a patch that was created using `git format-patch`, the
|
||||
best command to do this with is the `git am` command.
|
||||
|
||||
For example, within your repository, run:
|
||||
|
||||
|
@ -93,4 +134,5 @@ Applying: #2272799 Replaced URL
|
|||
|
||||
Each line is the commit message associated with that patch.
|
||||
|
||||
Assuming that there are no errors, you can go ahead and push your updated code into your remote repository.
|
||||
Assuming that there are no errors, you can go ahead and push your updated code
|
||||
into your remote repository.
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
---
|
||||
title: Going to DrupalCon
|
||||
date: 2013-07-26
|
||||
excerpt: Precedent are sending myself and two of our other Drupal Developers to Drupalcon Prague.
|
||||
excerpt:
|
||||
Precedent are sending myself and two of our other Drupal Developers to
|
||||
Drupalcon Prague.
|
||||
tags:
|
||||
- drupalcon
|
||||
- precedent
|
||||
---
|
||||
[Precedent](http://www.precedent.co.uk) are sending myself and two of our other Drupal Developers to [Drupalcon Prague](http://prague2013.drupal.org).
|
||||
|
||||
Having wanted to attend the last few Drupalcons (London, especially) but not being able to, I'm definitely looking forward to this one.
|
||||
[Precedent](http://www.precedent.co.uk) are sending myself and two of our other
|
||||
Drupal Developers to [Drupalcon Prague](http://prague2013.drupal.org).
|
||||
|
||||
Having wanted to attend the last few Drupalcons (London, especially) but not
|
||||
being able to, I'm definitely looking forward to this one.
|
||||
|
||||
See you there!
|
||||
|
|
|
@ -6,10 +6,30 @@ tags:
|
|||
- drupal-planet
|
||||
- imagefield-import
|
||||
---
|
||||
|
||||
I've finally uploaded my first module onto Drupal.org!
|
||||
|
||||
I've written many custom modules, although the vast majority of them are either small tweaks for my own sites, or company/site-specific modules that wouldn't be good to anyone else, so there would be nothing achieved by contributing them back to the community. Previously, I've blogged about the [Imagefield Import](http://drupal.org/project/imagefield_import) module - a module that I use on a number of sites, both personal and for clients - and what I've looked for lately is for a way to speed up the process again. Gathering my images together and manually copying them into the import directory takes time - especially if I'm working somewhere with a slow Internet connection and I'm FTP-ing the images into the directory. Also, it's not always the easiest solution for site users - especially non-technical ones.
|
||||
I've written many custom modules, although the vast majority of them are either
|
||||
small tweaks for my own sites, or company/site-specific modules that wouldn't be
|
||||
good to anyone else, so there would be nothing achieved by contributing them
|
||||
back to the community. Previously, I've blogged about the
|
||||
[Imagefield Import](http://drupal.org/project/imagefield_import) module - a
|
||||
module that I use on a number of sites, both personal and for clients - and what
|
||||
I've looked for lately is for a way to speed up the process again. Gathering my
|
||||
images together and manually copying them into the import directory takes time -
|
||||
especially if I'm working somewhere with a slow Internet connection and I'm
|
||||
FTP-ing the images into the directory. Also, it's not always the easiest
|
||||
solution for site users - especially non-technical ones.
|
||||
|
||||
So, I wrote the Imagefield Import Archive module. Including comments, the module contains 123 lines, and builds upon the existing functionality of the Imagefield Import module by adding the ability for the user to upload a .zip archive of images. The archive is then moved into the specified import directory and unzipped before being deleted, and the user is directed straight to the standard Imagefield Import page where their images are waiting to be imported, just as usual.
|
||||
So, I wrote the Imagefield Import Archive module. Including comments, the module
|
||||
contains 123 lines, and builds upon the existing functionality of the Imagefield
|
||||
Import module by adding the ability for the user to upload a .zip archive of
|
||||
images. The archive is then moved into the specified import directory and
|
||||
unzipped before being deleted, and the user is directed straight to the standard
|
||||
Imagefield Import page where their images are waiting to be imported, just as
|
||||
usual.
|
||||
|
||||
The module is currently a [sandbox project](http://drupal.org/sandbox/opdavies/1165110) on Drupal.org, although I have applied for full project access so that I can be added as a fully-fledged downloadable module.
|
||||
The module is currently a
|
||||
[sandbox project](http://drupal.org/sandbox/opdavies/1165110) on Drupal.org,
|
||||
although I have applied for full project access so that I can be added as a
|
||||
fully-fledged downloadable module.
|
||||
|
|
|
@ -7,11 +7,19 @@ tags:
|
|||
- drupal-6
|
||||
- imagecache
|
||||
---
|
||||
Whilst uploading images for my Projects and Testimonials sections, I noticed that the Imagecache-scaled images weren't as high a quality the originals on my Mac. I did some searching online and found out that, by default, Drupal resamples uploaded jpgs to 75% of their original quality.
|
||||
|
||||
To increase the quality of your images, change the setting in the two following places:
|
||||
Whilst uploading images for my Projects and Testimonials sections, I noticed
|
||||
that the Imagecache-scaled images weren't as high a quality the originals on my
|
||||
Mac. I did some searching online and found out that, by default, Drupal
|
||||
resamples uploaded jpgs to 75% of their original quality.
|
||||
|
||||
* admin/settings/imageapi/config
|
||||
* admin/settings/image-toolkit
|
||||
To increase the quality of your images, change the setting in the two following
|
||||
places:
|
||||
|
||||
The first one is for ImageAPI. Primarily, this means Imagecache presets. The second one is for core's image.inc. This is used for resizing profile pictures in core, and some contrib modules. Once changed, I did have to flush each of the Imagecache presets (admin/dist/imagecache) for the changes to take effect.
|
||||
- admin/settings/imageapi/config
|
||||
- admin/settings/image-toolkit
|
||||
|
||||
The first one is for ImageAPI. Primarily, this means Imagecache presets. The
|
||||
second one is for core's image.inc. This is used for resizing profile pictures
|
||||
in core, and some contrib modules. Once changed, I did have to flush each of the
|
||||
Imagecache presets (admin/dist/imagecache) for the changes to take effect.
|
||||
|
|
|
@ -8,9 +8,13 @@ tags:
|
|||
- fonts
|
||||
- sass
|
||||
---
|
||||
How to use an @each loop in SASS to quickly include multiple font files within your stylesheet.
|
||||
|
||||
Using a file structure similar to this, organise your font files into directories, using the the font name for both the directory name and for the file names.
|
||||
How to use an @each loop in SASS to quickly include multiple font files within
|
||||
your stylesheet.
|
||||
|
||||
Using a file structure similar to this, organise your font files into
|
||||
directories, using the the font name for both the directory name and for the
|
||||
file names.
|
||||
|
||||
```language-bash
|
||||
.
|
||||
|
@ -36,7 +40,9 @@ Using a file structure similar to this, organise your font files into directorie
|
|||
│ └── FuturaItalic.woff
|
||||
```
|
||||
|
||||
Within your SASS file, start an `@each` loop, listing the names of the fonts. In the same way as PHP's `foreach` loop, each font name will get looped through using the `$family` variable and then compiled into CSS.
|
||||
Within your SASS file, start an `@each` loop, listing the names of the fonts. In
|
||||
the same way as PHP's `foreach` loop, each font name will get looped through
|
||||
using the `$family` variable and then compiled into CSS.
|
||||
|
||||
```language-scss
|
||||
@each $family in FuturaBook, FuturaBold, FuturaBoldItalic, FuturaItalic {
|
||||
|
@ -53,7 +59,8 @@ Within your SASS file, start an `@each` loop, listing the names of the fonts. In
|
|||
}
|
||||
```
|
||||
|
||||
When the CSS has been compiled, you can then use in your CSS in the standard way.
|
||||
When the CSS has been compiled, you can then use in your CSS in the standard
|
||||
way.
|
||||
|
||||
```language-scss
|
||||
font-family: "FuturaBook";
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
---
|
||||
title: Include a Local Drupal Settings file for Environment Configuration and Overrides
|
||||
title:
|
||||
Include a Local Drupal Settings file for Environment Configuration and
|
||||
Overrides
|
||||
date: 2014-12-20
|
||||
excerpt: How to create and include a local settings file to define and override environment-specific variables.
|
||||
excerpt:
|
||||
How to create and include a local settings file to define and override
|
||||
environment-specific variables.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-6
|
||||
|
@ -10,7 +14,10 @@ tags:
|
|||
- drupal-planet
|
||||
- settings.php
|
||||
---
|
||||
How to create and include a local settings file to define and override environment-specific variables, and keep sensitive things like your database credentials and API keys safe.
|
||||
|
||||
How to create and include a local settings file to define and override
|
||||
environment-specific variables, and keep sensitive things like your database
|
||||
credentials and API keys safe.
|
||||
|
||||
At the bottom of settings.php, add the following code:
|
||||
|
||||
|
@ -21,17 +28,30 @@ if (file_exists($local_settings)) {
|
|||
}
|
||||
```
|
||||
|
||||
This allows for you to create a new file called settings.local.php within a sites/* directory (the same place as settings.php), and this will be included as an extension of settings.php. You can see the same technique being used within Drupal 8's [default.settings.php](http://cgit.drupalcode.org/drupal/tree/sites/default/default.settings.php#n621) file.
|
||||
This allows for you to create a new file called settings.local.php within a
|
||||
sites/\* directory (the same place as settings.php), and this will be included
|
||||
as an extension of settings.php. You can see the same technique being used
|
||||
within Drupal 8's
|
||||
[default.settings.php](http://cgit.drupalcode.org/drupal/tree/sites/default/default.settings.php#n621)
|
||||
file.
|
||||
|
||||
Environment specific settings like `$databases` and `$base_url` can be placed within the local settings file. Other settings like `$conf['locale_custom_strings_en']` (string overrides) and `$conf['allow_authorize_operations']` that would apply to all environments can still be placed in settings.php.
|
||||
Environment specific settings like `$databases` and `$base_url` can be placed
|
||||
within the local settings file. Other settings like
|
||||
`$conf['locale_custom_strings_en']` (string overrides) and
|
||||
`$conf['allow_authorize_operations']` that would apply to all environments can
|
||||
still be placed in settings.php.
|
||||
|
||||
settings.php though is ignored by default by Git by a .gitignore file, so it won't show up as a file available to be committed. There are two ways to fix this. The first is to use the `--force` option when adding the file which overrides the ignore file:
|
||||
settings.php though is ignored by default by Git by a .gitignore file, so it
|
||||
won't show up as a file available to be committed. There are two ways to fix
|
||||
this. The first is to use the `--force` option when adding the file which
|
||||
overrides the ignore file:
|
||||
|
||||
```language-bash
|
||||
git add --force sites/default/settings.php
|
||||
```
|
||||
|
||||
The other option is to update the .gitignore file itself so that settings.php is no longer ignored. An updated .gitignore file could look like:
|
||||
The other option is to update the .gitignore file itself so that settings.php is
|
||||
no longer ignored. An updated .gitignore file could look like:
|
||||
|
||||
```language-bash
|
||||
# Ignore configuration files that may contain sensitive information.
|
||||
|
@ -42,4 +62,5 @@ sites/*/files
|
|||
sites/*/private
|
||||
```
|
||||
|
||||
This will allow for settings.php to be added to Git and committed, but not settings.local.php.
|
||||
This will allow for settings.php to be added to Git and committed, but not
|
||||
settings.local.php.
|
||||
|
|
|
@ -7,17 +7,25 @@ tags:
|
|||
- ubuntu
|
||||
- version-control
|
||||
---
|
||||
Recently, I needed to set up a Subversion (SVN) server on a Ubuntu Linux server. This post is going to outline the steps taken, and the commands used, to install and configure the service.
|
||||
|
||||
Note: As I was using Ubuntu, I was using the 'apt-get' command to download and install the software packages. If you're using a different distribution of Linux, then this command may be different. I'm also assuming that Apache is already installed.
|
||||
Recently, I needed to set up a Subversion (SVN) server on a Ubuntu Linux server.
|
||||
This post is going to outline the steps taken, and the commands used, to install
|
||||
and configure the service.
|
||||
|
||||
Firstly, I'm going to ensure that all of my installed packages are up to date, and install any available updates.
|
||||
Note: As I was using Ubuntu, I was using the 'apt-get' command to download and
|
||||
install the software packages. If you're using a different distribution of
|
||||
Linux, then this command may be different. I'm also assuming that Apache is
|
||||
already installed.
|
||||
|
||||
Firstly, I'm going to ensure that all of my installed packages are up to date,
|
||||
and install any available updates.
|
||||
|
||||
```language-bash
|
||||
$ sudo apt-get update
|
||||
```
|
||||
|
||||
Now, I need to download the subversion, subversion-tools and libapache2 packages.
|
||||
Now, I need to download the subversion, subversion-tools and libapache2
|
||||
packages.
|
||||
|
||||
```language-bash
|
||||
$ sudo apt-get install subversion subversion-tools libapache2-svn
|
||||
|
@ -27,7 +35,9 @@ These are all of the packages that are needed to run a Subversion server.
|
|||
|
||||
## Create subversion directory
|
||||
|
||||
Now, I need to create the directory where my repositories are going to sit. I've chosen this directory as I know that it's one that is accessible to my managed backup service.
|
||||
Now, I need to create the directory where my repositories are going to sit. I've
|
||||
chosen this directory as I know that it's one that is accessible to my managed
|
||||
backup service.
|
||||
|
||||
```language-bash
|
||||
$ sudo mkdir /home/svn
|
||||
|
@ -35,7 +45,8 @@ $ sudo mkdir /home/svn
|
|||
|
||||
## Create a test repository
|
||||
|
||||
First, I'll create a new folder in which I'll create my test project, and then I'll create a repository for it.
|
||||
First, I'll create a new folder in which I'll create my test project, and then
|
||||
I'll create a repository for it.
|
||||
|
||||
```language-bash
|
||||
$ sudo mkdir ~/test
|
||||
|
@ -59,7 +70,10 @@ $ sudo svn import ~/test file:///home/svn/test -m 'Initial project directories'
|
|||
|
||||
This both adds and commits these new directories into the repository.
|
||||
|
||||
In order for Apache to access the SVN repositories, the `/home/svn` directory needs to be owned by the same user and group that Apache runs as. In Ubuntu, this is usually www-data. To change the owner of a directory, use the chown command.
|
||||
In order for Apache to access the SVN repositories, the `/home/svn` directory
|
||||
needs to be owned by the same user and group that Apache runs as. In Ubuntu,
|
||||
this is usually www-data. To change the owner of a directory, use the chown
|
||||
command.
|
||||
|
||||
```language-bash
|
||||
$ sudo chown -R www-data:www-data /home/svn
|
||||
|
@ -67,7 +81,8 @@ $ sudo chown -R www-data:www-data /home/svn
|
|||
|
||||
## Configuring Apache
|
||||
|
||||
The first thing that I need to do is enable the dav_svn Apache module, using the a2enmod command.
|
||||
The first thing that I need to do is enable the dav_svn Apache module, using the
|
||||
a2enmod command.
|
||||
|
||||
```language-bash
|
||||
$ sudo a2enmod dav_svn
|
||||
|
@ -80,7 +95,8 @@ $ cd /etc/apache2
|
|||
$ sudo nano apache2.conf
|
||||
```
|
||||
|
||||
At the bottom of the file, add the following lines, and then save the file by pressing Ctrl+X.
|
||||
At the bottom of the file, add the following lines, and then save the file by
|
||||
pressing Ctrl+X.
|
||||
|
||||
```language-apacheconf
|
||||
<Location "/svn">
|
||||
|
@ -95,11 +111,17 @@ With this saved, restart the Apache service for the changes to be applied.
|
|||
sudo service apache2 restart
|
||||
```
|
||||
|
||||
I can now browse through my test repository by opening Firefox, and navigating to `http://127.0.0.1/svn/test`. Here, I can now see my three directories, although they are currently all empty.
|
||||
I can now browse through my test repository by opening Firefox, and navigating
|
||||
to `http://127.0.0.1/svn/test`. Here, I can now see my three directories,
|
||||
although they are currently all empty.
|
||||
|
||||
## Securing my SVN repositories
|
||||
|
||||
Before I start committing any files to the test repository, I want to ensure that only authorised users can view it - currently anyone can view the repository and it's contents, as well as being able to checkout and commit files. To do this, I'm going to require the user to enter a username and a password before viewing or performing any actions with the repository.
|
||||
Before I start committing any files to the test repository, I want to ensure
|
||||
that only authorised users can view it - currently anyone can view the
|
||||
repository and it's contents, as well as being able to checkout and commit
|
||||
files. To do this, I'm going to require the user to enter a username and a
|
||||
password before viewing or performing any actions with the repository.
|
||||
|
||||
Re-open apache2.conf, and replace the SVN Location information with this:
|
||||
|
||||
|
@ -120,11 +142,15 @@ Now I need to create the password file.
|
|||
$ htpasswd -cm /etc/svn-auth oliver
|
||||
```
|
||||
|
||||
I'm prompted to enter and confirm my password, and then my details are saved. The Apache service will need to be restarted again, and then the user will need to authenticate themselves before viewing the repositories.
|
||||
I'm prompted to enter and confirm my password, and then my details are saved.
|
||||
The Apache service will need to be restarted again, and then the user will need
|
||||
to authenticate themselves before viewing the repositories.
|
||||
|
||||
## Checking out the repository and commiting files
|
||||
|
||||
For example, now want to checkout the files within my repository into a new directory called 'test2' within my home directory. Firstly, I need to create the new directory, and then I can issue the checkout command.
|
||||
For example, now want to checkout the files within my repository into a new
|
||||
directory called 'test2' within my home directory. Firstly, I need to create the
|
||||
new directory, and then I can issue the checkout command.
|
||||
|
||||
```language-bash
|
||||
$ cd ~
|
||||
|
@ -132,13 +158,21 @@ $ mkdir test2
|
|||
$ svn checkout http://127.0.0.1/svn/test/trunk test2
|
||||
```
|
||||
|
||||
I'm passing the command two arguments - the first is the URL of the repository's trunk directory, and the second is the directory where the files are to be placed. As no files have been commited yet into the trunk, it appears to be empty - but if you perform an ls -la command, you'll see that there is a hidden .svn directory.
|
||||
I'm passing the command two arguments - the first is the URL of the repository's
|
||||
trunk directory, and the second is the directory where the files are to be
|
||||
placed. As no files have been commited yet into the trunk, it appears to be
|
||||
empty - but if you perform an ls -la command, you'll see that there is a hidden
|
||||
.svn directory.
|
||||
|
||||
Now you can start adding files into the directory. Once you've created your files, perform a svn add command, passing in individual filenames as further arguments.
|
||||
Now you can start adding files into the directory. Once you've created your
|
||||
files, perform a svn add command, passing in individual filenames as further
|
||||
arguments.
|
||||
|
||||
```language-bash
|
||||
$ svn add index.php
|
||||
$ svn add *
|
||||
```
|
||||
|
||||
With all the required files added, they can be committed using `svn commit -m 'commit message'` command, and the server can be updated using the svn up command.
|
||||
With all the required files added, they can be committed using
|
||||
`svn commit -m 'commit message'` command, and the server can be updated using
|
||||
the svn up command.
|
||||
|
|
|
@ -1,23 +1,33 @@
|
|||
---
|
||||
title: Install and Configure the Nomensa Accessible Media Player in Drupal
|
||||
date: 2012-07-14
|
||||
excerpt: This week I released the first version of the Nomensa Accessible Media Player module for Drupal 7. Here's some instructions of how to install and configure it.
|
||||
excerpt:
|
||||
This week I released the first version of the Nomensa Accessible Media Player
|
||||
module for Drupal 7. Here's some instructions of how to install and configure
|
||||
it.
|
||||
tags:
|
||||
- accessibility
|
||||
- drupal
|
||||
- drupal-planet
|
||||
- nomensa
|
||||
---
|
||||
This week I released the first version of the Nomensa Accessible Media Player module for Drupal 7. Here's some instructions of how to install and configure it.
|
||||
|
||||
*The official documentation for this module is now located at <https://www.drupal.org/node/2383447>. This post was accurate at the time of writing, whereas the documentation page will be kept up to date with any future changes.*
|
||||
This week I released the first version of the Nomensa Accessible Media Player
|
||||
module for Drupal 7. Here's some instructions of how to install and configure
|
||||
it.
|
||||
|
||||
_The official documentation for this module is now located at
|
||||
<https://www.drupal.org/node/2383447>. This post was accurate at the time of
|
||||
writing, whereas the documentation page will be kept up to date with any future
|
||||
changes._
|
||||
|
||||
## Initial configuration
|
||||
|
||||
### Download the Library
|
||||
|
||||
The library can be downloaded directly from GitHub, and should be placed within you *sites/all/libraries/nomensa_amp* directory.
|
||||
|
||||
The library can be downloaded directly from GitHub, and should be placed within
|
||||
you _sites/all/libraries/nomensa_amp_ directory.
|
||||
|
||||
```language-bash
|
||||
drush dl libraries nomensa_amp
|
||||
git clone https://github.com/nomensa/Accessible-Media-Player sites/all/libraries/nomensa_amp
|
||||
|
@ -28,7 +38,8 @@ drush en -y nomensa_amp
|
|||
|
||||
### Configure the Module
|
||||
|
||||
Configure the module at <em>admin/config/media/nomensa-amp</em> and enable the players that you want to use.
|
||||
Configure the module at <em>admin/config/media/nomensa-amp</em> and enable the
|
||||
players that you want to use.
|
||||
|
||||
## Adding videos
|
||||
|
||||
|
@ -48,11 +59,13 @@ Within your content add links to your videos. For example:
|
|||
|
||||
## Adding captions
|
||||
|
||||
The best way that I can suggest to do this is to use a File field to upload your captions file:
|
||||
The best way that I can suggest to do this is to use a File field to upload your
|
||||
captions file:
|
||||
|
||||
1. Add a File field to your content type;
|
||||
1. On your page upload the captions file.
|
||||
1. Right-click the uploaded file, copy the link location, and use this for the path to your captions file.
|
||||
1. Right-click the uploaded file, copy the link location, and use this for the
|
||||
path to your captions file.
|
||||
|
||||
For example:
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ tags:
|
|||
- centos
|
||||
- linux
|
||||
---
|
||||
A great post details that details the steps needed to install [Nagios](http://nagios.org) - a popular open source system and network monitoring software application - on CentOS.
|
||||
|
||||
A great post details that details the steps needed to install
|
||||
[Nagios](http://nagios.org) - a popular open source system and network
|
||||
monitoring software application - on CentOS.
|
||||
|
||||
<http://saylinux.net/story/009506/how-install-nagios-centos-55>
|
||||
|
|
|
@ -3,19 +3,27 @@ title: Introducing the Drupal Meetups Twitterbot
|
|||
date: 2017-06-09
|
||||
excerpt: I’ve written a twitterbot for promoting Drupal meetups.
|
||||
tags:
|
||||
- twitter
|
||||
- php
|
||||
- twitter
|
||||
- php
|
||||
---
|
||||
|
||||
<p class="text-center" markdown="1">![](/images/blog/drupal-meetups-twitterbot.png)</p>
|
||||
|
||||
The [Drupal Meetups Twitterbot][0] is a small project that I worked on a few months ago, but hadn't got around to promoting yet. It’s intention is to provide [one Twitter account][1] where people can get the up to date news from various Drupal meetups.
|
||||
The [Drupal Meetups Twitterbot][0] is a small project that I worked on a few
|
||||
months ago, but hadn't got around to promoting yet. It’s intention is to provide
|
||||
[one Twitter account][1] where people can get the up to date news from various
|
||||
Drupal meetups.
|
||||
|
||||
It works by having a whitelist of [Twitter accounts and hashtags][2] to search for, uses [Codebird][3] to query the Twitter API and retweets any matching tweets on a scheduled basis.
|
||||
It works by having a whitelist of [Twitter accounts and hashtags][2] to search
|
||||
for, uses [Codebird][3] to query the Twitter API and retweets any matching
|
||||
tweets on a scheduled basis.
|
||||
|
||||
If you would like your meetup group to be added to the list of searched accounts, please [open an issue][4] on the GitHub repo.
|
||||
If you would like your meetup group to be added to the list of searched
|
||||
accounts, please [open an issue][4] on the GitHub repo.
|
||||
|
||||
[0]: https://github.com/opdavies/drupal-meetups-twitterbot
|
||||
[1]: https://twitter.com/drupal_meetups
|
||||
[2]: https://github.com/opdavies/drupal-meetups-twitterbot/blob/master/bootstrap/config.php
|
||||
[2]:
|
||||
https://github.com/opdavies/drupal-meetups-twitterbot/blob/master/bootstrap/config.php
|
||||
[3]: https://www.jublo.net/projects/codebird/php
|
||||
[4]: https://github.com/opdavies/drupal-meetups-twitterbot/issues/new
|
||||
|
|
|
@ -1,14 +1,34 @@
|
|||
---
|
||||
title: Leaving Nomensa, Joining Precedent
|
||||
date: 2013-04-20
|
||||
excerpt: Yesterday was my last day working at Nomensa. Next week, I'll be starting as a Senior Developer at Precedent.
|
||||
excerpt:
|
||||
Yesterday was my last day working at Nomensa. Next week, I'll be starting as a
|
||||
Senior Developer at Precedent.
|
||||
tags:
|
||||
- nomensa
|
||||
- precedent
|
||||
- personal
|
||||
---
|
||||
Yesterday was my last day working at [Nomensa](http://www.nomensa.com "Nomensa"). Next week, I'll be starting as a Senior Developer at [Precedent](http://www.precedent.co.uk "Precedent").
|
||||
|
||||
The last 14 months that I've been working at Nomensa have been absolutely fantastic, and had allowed me to work on some great projects for great clients - mainly [unionlearn](http://www.unionlearn.org "unionlearn") and [Digital Theatre Plus](http://www.digitaltheatreplus.com "Digital Theatre Plus"). I've learned so much about accessibility and web standards, and have pretty much changed my whole approach to front-end development to accommodate best practices. I've also been involved with the Drupal Accessibility group since starting at Nomensa, and have written several accessibility-focused Drupal modules, including the [Nomensa Accessible Media Player](http://drupal.org/project/nomensa_amp "The Nomensa Accessible Media Player Drupal module") module and the [Accessibility Checklist](http://drupal.org/project/a11y_checklist "The accessibility checklist for Drupal"). I'll definitely be continuing my interest in accessibility, championing best practices, and incorporating it into my future work wherever possible.
|
||||
Yesterday was my last day working at
|
||||
[Nomensa](http://www.nomensa.com 'Nomensa'). Next week, I'll be starting as a
|
||||
Senior Developer at [Precedent](http://www.precedent.co.uk 'Precedent').
|
||||
|
||||
With that all said, I'm really looking forward to starting my new role at Precedent, tackling some new challenges, and I'm sure that it'll be as great a place to work as Nomensa was.
|
||||
The last 14 months that I've been working at Nomensa have been absolutely
|
||||
fantastic, and had allowed me to work on some great projects for great clients -
|
||||
mainly [unionlearn](http://www.unionlearn.org 'unionlearn') and
|
||||
[Digital Theatre Plus](http://www.digitaltheatreplus.com 'Digital Theatre Plus').
|
||||
I've learned so much about accessibility and web standards, and have pretty much
|
||||
changed my whole approach to front-end development to accommodate best
|
||||
practices. I've also been involved with the Drupal Accessibility group since
|
||||
starting at Nomensa, and have written several accessibility-focused Drupal
|
||||
modules, including the
|
||||
[Nomensa Accessible Media Player](http://drupal.org/project/nomensa_amp 'The Nomensa Accessible Media Player Drupal module')
|
||||
module and the
|
||||
[Accessibility Checklist](http://drupal.org/project/a11y_checklist 'The accessibility checklist for Drupal').
|
||||
I'll definitely be continuing my interest in accessibility, championing best
|
||||
practices, and incorporating it into my future work wherever possible.
|
||||
|
||||
With that all said, I'm really looking forward to starting my new role at
|
||||
Precedent, tackling some new challenges, and I'm sure that it'll be as great a
|
||||
place to work as Nomensa was.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,38 +1,60 @@
|
|||
---
|
||||
title: Looking forward to DrupalCamp London
|
||||
date: 2018-02-27
|
||||
excerpt: This weekend is DrupalCamp London 2018. I’ll be there along with a number of my Microserve colleagues.
|
||||
excerpt:
|
||||
This weekend is DrupalCamp London 2018. I’ll be there along with a number of
|
||||
my Microserve colleagues.
|
||||
tags:
|
||||
- drupal
|
||||
- drupalcamp
|
||||
- drupalcamp-london
|
||||
- speaking
|
||||
- drupal
|
||||
- drupalcamp
|
||||
- drupalcamp-london
|
||||
- speaking
|
||||
---
|
||||
This weekend is [DrupalCamp London 2018][1]. I’ll be there along with a number of my [Microserve][2] colleagues.
|
||||
|
||||
I look forward to DrupalCamp London every year, partly because it was the first DrupalCamp that I attended back in 2014. It was also the first DrupalCamp that I [gave a talk][3] at, when I presented a session about Git Flow having given only one user group talk before.
|
||||
This weekend is [DrupalCamp London 2018][1]. I’ll be there along with a number
|
||||
of my [Microserve][2] colleagues.
|
||||
|
||||
I’ve presented sessions at every DrupalCamp London since (including two last year), and I’m lucky enough to be [speaking again this year][4] due to one of the originally announced speakers no longer being able to make it to the event.
|
||||
I look forward to DrupalCamp London every year, partly because it was the first
|
||||
DrupalCamp that I attended back in 2014. It was also the first DrupalCamp that I
|
||||
[gave a talk][3] at, when I presented a session about Git Flow having given only
|
||||
one user group talk before.
|
||||
|
||||
I’ve presented sessions at every DrupalCamp London since (including two last
|
||||
year), and I’m lucky enough to be [speaking again this year][4] due to one of
|
||||
the originally announced speakers no longer being able to make it to the event.
|
||||
|
||||
Here are some other sessions that I’m hoping to see (in no particular order):
|
||||
|
||||
- Keynote by [Ryan Szrama][5] from [Commerce Guys][6]
|
||||
- [Drupal 8 Services And Dependency Injection](https://drupalcamp.london/session/drupal-8-services-and-dependency-injection) by Phil Norton
|
||||
- [Growing developers with Drupal](https://drupalcamp.london/session/growing-developers-drupal) by Fran Garcia-Linares (fjgarlin)
|
||||
- [How to make it easier for newcomers to get involved in Drupal](https://drupalcamp.london/session/how-make-it-easier-newcomers-get-involved-drupal) by heather
|
||||
- [Let’s take the best route - Exploring Drupal 8 Routing System](https://drupalcamp.london/session/lets-take-best-route-exploring-drupal-8-routing-system) by surbhi
|
||||
- [New recipe of Decoupling: Drupal 8, Symfony and Slim Framework](https://drupalcamp.london/session/new-recipe-decoupling-drupal-8-symfony-and-slim-framework) by Jyoti Singh
|
||||
- [Plugin API by examples](https://drupalcamp.london/session/plugin-api-examples) by Gabriele (gambry)
|
||||
- [Value of mentorship in the community](https://drupalcamp.london/session/value-mentorship-community) by Hussain Abbas (hussainweb)
|
||||
- [Warden - Helping Drupal Agencies Sleep at Night](https://drupalcamp.london/session/warden-helping-drupal-agencies-sleep-night) by Mike Davis
|
||||
- [Drupal 8 Services And Dependency Injection](https://drupalcamp.london/session/drupal-8-services-and-dependency-injection)
|
||||
by Phil Norton
|
||||
- [Growing developers with Drupal](https://drupalcamp.london/session/growing-developers-drupal)
|
||||
by Fran Garcia-Linares (fjgarlin)
|
||||
- [How to make it easier for newcomers to get involved in Drupal](https://drupalcamp.london/session/how-make-it-easier-newcomers-get-involved-drupal)
|
||||
by heather
|
||||
- [Let’s take the best route - Exploring Drupal 8 Routing System](https://drupalcamp.london/session/lets-take-best-route-exploring-drupal-8-routing-system)
|
||||
by surbhi
|
||||
- [New recipe of Decoupling: Drupal 8, Symfony and Slim Framework](https://drupalcamp.london/session/new-recipe-decoupling-drupal-8-symfony-and-slim-framework)
|
||||
by Jyoti Singh
|
||||
- [Plugin API by examples](https://drupalcamp.london/session/plugin-api-examples)
|
||||
by Gabriele (gambry)
|
||||
- [Value of mentorship in the community](https://drupalcamp.london/session/value-mentorship-community)
|
||||
by Hussain Abbas (hussainweb)
|
||||
- [Warden - Helping Drupal Agencies Sleep at Night](https://drupalcamp.london/session/warden-helping-drupal-agencies-sleep-night)
|
||||
by Mike Davis
|
||||
|
||||
Unfortunately there are some time slots where I’d like to see more than one of the talks (including when I’m going to be speaking). This regularly happens at conferences, but I’ll look forward to watching those on [YouTube][7] after the event.
|
||||
Unfortunately there are some time slots where I’d like to see more than one of
|
||||
the talks (including when I’m going to be speaking). This regularly happens at
|
||||
conferences, but I’ll look forward to watching those on [YouTube][7] after the
|
||||
event.
|
||||
|
||||
I’m also looking forward to catching up with former colleagues, spending some time in the "hallway track" and hopefully doing some sprinting too!
|
||||
I’m also looking forward to catching up with former colleagues, spending some
|
||||
time in the "hallway track" and hopefully doing some sprinting too!
|
||||
|
||||
## Finally
|
||||
|
||||
For nostalgia, [here’s the blog post][0] that I wrote before I attended my first DrupalCamp London.
|
||||
For nostalgia, [here’s the blog post][0] that I wrote before I attended my first
|
||||
DrupalCamp London.
|
||||
|
||||
See everyone this weekend!
|
||||
|
||||
|
|
|
@ -3,38 +3,65 @@ title: Yay, the Mediacurrent Contrib Half Hour is Back!
|
|||
date: 2018-03-02
|
||||
excerpt: Mediacurrent’s "contrib half hour sessions" are back.
|
||||
tags:
|
||||
- contribution
|
||||
- drupal
|
||||
- open-source
|
||||
- contribution
|
||||
- drupal
|
||||
- open-source
|
||||
has_tweets: true
|
||||
---
|
||||
Back in November, [Mediacurrent introduced][1] the contrib half hour - a weekly online meeting to provide guidance and assistance on contributing to Drupal and Drupal projects. A range of topics were covered in the first few sessions, including finding and testing bug fixes, Composer, Drush, and how to re-roll patches.
|
||||
|
||||
Back in November, [Mediacurrent introduced][1] the contrib half hour - a weekly
|
||||
online meeting to provide guidance and assistance on contributing to Drupal and
|
||||
Drupal projects. A range of topics were covered in the first few sessions,
|
||||
including finding and testing bug fixes, Composer, Drush, and how to re-roll
|
||||
patches.
|
||||
|
||||
From Damien's [introductory blog post][2]:
|
||||
|
||||
> Not sure what this whole "patch" thing is? Have a core change that you can't quite finish? Running into a problem with a contrib module, or a theme, or a 3rd party library, and not sure how to fix it? New to maintaining a module and unsure of what to do next? Wondering how to get your module through the security opt-in process? Is your project's issue queue getting you down? Join us every Thursday at noon EST for the Mediacurrent Contrib Half Hour where we'll be available to help solve contrib challenges.
|
||||
> Not sure what this whole "patch" thing is? Have a core change that you can't
|
||||
> quite finish? Running into a problem with a contrib module, or a theme, or a
|
||||
> 3rd party library, and not sure how to fix it? New to maintaining a module and
|
||||
> unsure of what to do next? Wondering how to get your module through the
|
||||
> security opt-in process? Is your project's issue queue getting you down? Join
|
||||
> us every Thursday at noon EST for the Mediacurrent Contrib Half Hour where
|
||||
> we'll be available to help solve contrib challenges.
|
||||
>
|
||||
> Each week we'll host a live meeting to give step-by-step guidance on some best practices for contributing to Drupal, and provide Q and A assistance for our favorite open source (OSS) content management system (CMS). The meetings will be lead by yours truly, Damien McKenna, a prolific contributor to the Drupal community, and my coworkers here at Mediacurrent.
|
||||
> Each week we'll host a live meeting to give step-by-step guidance on some best
|
||||
> practices for contributing to Drupal, and provide Q and A assistance for our
|
||||
> favorite open source (OSS) content management system (CMS). The meetings will
|
||||
> be lead by yours truly, Damien McKenna, a prolific contributor to the Drupal
|
||||
> community, and my coworkers here at Mediacurrent.
|
||||
|
||||
There is also an [updates blog post][3] that continues to show the latest information, and the video recordings are [uploaded to YouTube][0] after the session. Here is the first one from November:
|
||||
There is also an [updates blog post][3] that continues to show the latest
|
||||
information, and the video recordings are [uploaded to YouTube][0] after the
|
||||
session. Here is the first one from November:
|
||||
|
||||
<!-- <div class="talk-video mb-4">
|
||||
<iframe width="678" height="408" src="//www.youtube.com/embed/8xHE5y1rA1g" frameborder="0" allowfullscreen></iframe>
|
||||
</div> -->
|
||||
|
||||
I enjoyed watching the first few videos, as I’m always interested in contribution to Drupal and open-source and how to encourage it, but then no new videos were uploaded for a while and I hoped that it hadn’t faded away.
|
||||
I enjoyed watching the first few videos, as I’m always interested in
|
||||
contribution to Drupal and open-source and how to encourage it, but then no new
|
||||
videos were uploaded for a while and I hoped that it hadn’t faded away.
|
||||
|
||||
I’m glad to see today that it’s back and that all of the previous videos have been uploaded and added to the [YouTube playlist][0], and that [on the update post][3] there are scheduled topics for the rest of this month including documentation and automated testing.
|
||||
I’m glad to see today that it’s back and that all of the previous videos have
|
||||
been uploaded and added to the [YouTube playlist][0], and that [on the update
|
||||
post][3] there are scheduled topics for the rest of this month including
|
||||
documentation and automated testing.
|
||||
|
||||
<div class="mb-4">
|
||||
<blockquote class="twitter-tweet" data-cards="hidden" data-lang="en"><p lang="en" dir="ltr">All of the <a href="https://twitter.com/mediacurrent?ref_src=twsrc%5Etfw">@mediacurrent</a> <a href="https://twitter.com/hashtag/ContribHalfHour?src=hash&ref_src=twsrc%5Etfw">#ContribHalfHour</a> videos have been uploaded to our Youtube channel: <a href="https://t.co/1sWZT5sRSN">https://t.co/1sWZT5sRSN</a><br>Note: I accidentally forgot to save the Feb 22nd video, sorry :-\</p>— Damien McKenna (@DamienMcKenna) <a href="https://twitter.com/DamienMcKenna/status/969668677980315649?ref_src=twsrc%5Etfw">March 2, 2018</a></blockquote>
|
||||
</div>
|
||||
|
||||
I do enjoy watching these, and I like both the presentation and Q&A format that they alternate between. I’ll look forward to catching up over the next few days, and to hopefully seeing them continue to be uploaded after future meetings.
|
||||
I do enjoy watching these, and I like both the presentation and Q&A format that
|
||||
they alternate between. I’ll look forward to catching up over the next few days,
|
||||
and to hopefully seeing them continue to be uploaded after future meetings.
|
||||
|
||||
Thanks Damien and Mediacurrent!
|
||||
|
||||
[0]: https://www.youtube.com/playlist?list=PLu-MxhbnjI9rHroPvZO5LEUhr58Yl0j_F
|
||||
[1]: https://www.mediacurrent.com/blog/introducing-mediacurrent-contrib-half-hour
|
||||
[2]: https://www.mediacurrent.com/blog/introducing-mediacurrent-contrib-half-hour
|
||||
[3]: https://www.mediacurrent.com/blog/updates-mediacurrent-contrib-half-hour-weekly-meeting
|
||||
[1]:
|
||||
https://www.mediacurrent.com/blog/introducing-mediacurrent-contrib-half-hour
|
||||
[2]:
|
||||
https://www.mediacurrent.com/blog/introducing-mediacurrent-contrib-half-hour
|
||||
[3]:
|
||||
https://www.mediacurrent.com/blog/updates-mediacurrent-contrib-half-hour-weekly-meeting
|
||||
|
|
|
@ -9,32 +9,52 @@ tags:
|
|||
meta:
|
||||
og:
|
||||
title: 'How to Define a Minimum Drupal Core Version'
|
||||
excerpt: 'How to define a minimum Drupal core version for your module or theme.'
|
||||
excerpt:
|
||||
'How to define a minimum Drupal core version for your module or theme.'
|
||||
type: article
|
||||
---
|
||||
This week, my first code patch was [committed to Drupal core](https://www.drupal.org/node/2394517#comment-9773143). The patch adds the `user_has_role()` function to the user module, to simplify the way to check whether a user in Drupal has been assigned a specific role. This is something that I normally write a custom function for each project, but it's now available in Drupal core as of [7.36](https://www.drupal.org/drupal-7.36-release-notes).
|
||||
|
||||
But what if someone is using a core version less than 7.36 and tries using the function? The site would return an error because that function wouldn't exist.
|
||||
This week, my first code patch was
|
||||
[committed to Drupal core](https://www.drupal.org/node/2394517#comment-9773143).
|
||||
The patch adds the `user_has_role()` function to the user module, to simplify
|
||||
the way to check whether a user in Drupal has been assigned a specific role.
|
||||
This is something that I normally write a custom function for each project, but
|
||||
it's now available in Drupal core as of
|
||||
[7.36](https://www.drupal.org/drupal-7.36-release-notes).
|
||||
|
||||
If you're building a new Drupal site, then I'd assume that you're using a latest version of core, or you have the opportunity to update it when needed. But what if you're writing a contrib module? How can you be sure that the correct minimum version of core?
|
||||
But what if someone is using a core version less than 7.36 and tries using the
|
||||
function? The site would return an error because that function wouldn't exist.
|
||||
|
||||
If you're building a new Drupal site, then I'd assume that you're using a latest
|
||||
version of core, or you have the opportunity to update it when needed. But what
|
||||
if you're writing a contrib module? How can you be sure that the correct minimum
|
||||
version of core?
|
||||
|
||||
## Setting Dependencies
|
||||
|
||||
What I'm going to be doing for my contrib projects is defining a minimum version of Drupal core that the module is compatible with. If this dependency isn't met, the module won't be able to be enabled. This is done within your module's .info file.
|
||||
What I'm going to be doing for my contrib projects is defining a minimum version
|
||||
of Drupal core that the module is compatible with. If this dependency isn't met,
|
||||
the module won't be able to be enabled. This is done within your module's .info
|
||||
file.
|
||||
|
||||
### Adding a Simple Dependency
|
||||
|
||||
You can define a simple dependency for your module by adding a line this this to your project's .info file:
|
||||
You can define a simple dependency for your module by adding a line this this to
|
||||
your project's .info file:
|
||||
|
||||
```language-bash
|
||||
dependencies[] = views
|
||||
```
|
||||
|
||||
This would make your module dependant on having the [Views](https://www.drupal.org/project/views) module present and enabled, which you'd need if you were including views as part of your module, for example.
|
||||
This would make your module dependant on having the
|
||||
[Views](https://www.drupal.org/project/views) module present and enabled, which
|
||||
you'd need if you were including views as part of your module, for example.
|
||||
|
||||
### Adding a Complex Dependency
|
||||
|
||||
In the previous example, our module would enable if _any_ version of Views was enabled, but we need to specify a specific version. We can do this by including version numbers within the dependencies field in the following format:
|
||||
In the previous example, our module would enable if _any_ version of Views was
|
||||
enabled, but we need to specify a specific version. We can do this by including
|
||||
version numbers within the dependencies field in the following format:
|
||||
|
||||
```language-bash
|
||||
dependencies[] = modulename (major.minor)
|
||||
|
@ -49,23 +69,29 @@ dependencies[] = modulename (1.x)
|
|||
|
||||
We can also use the following as part of the field for extra granularity:
|
||||
|
||||
* = or == equals (this is the default)
|
||||
* > greater than
|
||||
* < lesser than
|
||||
* >= greater than or equal to
|
||||
* <= lesser than or equal to
|
||||
* != not equal to
|
||||
- = or == equals (this is the default)
|
||||
- > greater than
|
||||
- < lesser than
|
||||
- > = greater than or equal to
|
||||
- <= lesser than or equal to
|
||||
- != not equal to
|
||||
|
||||
In the original scenario, we want to specify that the module can only be enabled on Drupal core 7.36 or later. To do this, we can use the "greater than or equal to" option.
|
||||
In the original scenario, we want to specify that the module can only be enabled
|
||||
on Drupal core 7.36 or later. To do this, we can use the "greater than or equal
|
||||
to" option.
|
||||
|
||||
```language-ini
|
||||
dependencies[] = system (>=7.36)
|
||||
```
|
||||
|
||||
Because we need to check for Drupal's core version, we're using the system module as the dependency and specifying that it needs to be either equal to or greater than 7.36. If this dependency is not met, e.g. Drupal 7.35 is being used, then the module cannot be enabled rather than showing a function not found error for `user_has_role()` when it is called.
|
||||
Because we need to check for Drupal's core version, we're using the system
|
||||
module as the dependency and specifying that it needs to be either equal to or
|
||||
greater than 7.36. If this dependency is not met, e.g. Drupal 7.35 is being
|
||||
used, then the module cannot be enabled rather than showing a function not found
|
||||
error for `user_has_role()` when it is called.
|
||||
|
||||
![A screenshot of the modules page showing System as a dependency for a custom module.](/images/blog/minimum-drupal-version-d7.png)
|
||||
|
||||
## External Links
|
||||
|
||||
* [Writing module .info files (Drupal 7.x)](https://www.drupal.org/node/542202#dependencies)
|
||||
- [Writing module .info files (Drupal 7.x)](https://www.drupal.org/node/542202#dependencies)
|
||||
|
|
|
@ -10,9 +10,15 @@ tags:
|
|||
- drupal-planet
|
||||
- accessibility
|
||||
---
|
||||
|
||||
After a busy few days, I've released two new contrib Drupal modules.
|
||||
|
||||
* [Block Aria Landmark Roles](http://drupal.org/project/block_aria_landmark_roles) - Inspired by [Block Class](http://drupal.org/project/block_class), this module adds additional elements to the block configuration forms that allow users to assign a ARIA landmark role to a block.
|
||||
* [Nomensa Accessible Media Player](http://drupal.org/project/nomensa_amp) - Provides integration with Nomensa's [Accessible Media Player](https://github.com/nomensa/Accessible-Media-Player).
|
||||
- [Block Aria Landmark Roles](http://drupal.org/project/block_aria_landmark_roles) -
|
||||
Inspired by [Block Class](http://drupal.org/project/block_class), this module
|
||||
adds additional elements to the block configuration forms that allow users to
|
||||
assign a ARIA landmark role to a block.
|
||||
- [Nomensa Accessible Media Player](http://drupal.org/project/nomensa_amp) -
|
||||
Provides integration with Nomensa's
|
||||
[Accessible Media Player](https://github.com/nomensa/Accessible-Media-Player).
|
||||
|
||||
Documentation for both to follow shortly on Drupal.org.
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
---
|
||||
title: My Sublime Text 2 settings
|
||||
date: 2012-10-25
|
||||
excerpt: <a href="http://www.sublimetext.com/2" title="Sublime Text 2">Sublime Text 2</a> has been my text editor of choice for the past few months, and I use it at home, in work, and on any virtual machines that I run. So rather than having to manually re-enter my settings each time, I thought that I'd document them here for future reference.
|
||||
excerpt:
|
||||
<a href="http://www.sublimetext.com/2" title="Sublime Text 2">Sublime Text
|
||||
2</a> has been my text editor of choice for the past few months, and I use it
|
||||
at home, in work, and on any virtual machines that I run. So rather than
|
||||
having to manually re-enter my settings each time, I thought that I'd document
|
||||
them here for future reference.
|
||||
tags:
|
||||
- sublime-text
|
||||
---
|
||||
[Sublime Text 2](http://www.sublimetext.com/2) has been my text editor of choice for the past few months, and I use it at home, in work, and on any virtual machines that I run. So rather than having to manually re-enter my settings each time, I thought that I'd document them here for future reference.
|
||||
|
||||
These preferences ensure that the code is compliant with [Drupal coding standards](http://drupal.org/coding-standards "Drupal coding standards on Drupal.org") - using two spaces instead of a tab, no trailing whitespace, blank line at the end of a file etc.
|
||||
[Sublime Text 2](http://www.sublimetext.com/2) has been my text editor of choice
|
||||
for the past few months, and I use it at home, in work, and on any virtual
|
||||
machines that I run. So rather than having to manually re-enter my settings each
|
||||
time, I thought that I'd document them here for future reference.
|
||||
|
||||
These preferences ensure that the code is compliant with
|
||||
[Drupal coding standards](http://drupal.org/coding-standards 'Drupal coding standards on Drupal.org') -
|
||||
using two spaces instead of a tab, no trailing whitespace, blank line at the end
|
||||
of a file etc.
|
||||
|
||||
## Preferences
|
||||
|
||||
|
@ -91,9 +103,9 @@ These can be changed by going to Preferences > Key Bindings - User.
|
|||
|
||||
These are the packages that I currently have installed.
|
||||
|
||||
* [DocBlockr](https://github.com/spadgos/sublime-jsdocs "DocBlockr on GitHub")
|
||||
* [Drupal API](https://github.com/BrianGilbert/Sublime-Text-2-Goto-Drupal-API)
|
||||
* [LESS](https://github.com/danro/LESS-sublime)
|
||||
* [Package Control](http://wbond.net/sublime_packages/package_control)
|
||||
* [Sublime CodeIntel](http://github.com/Kronuz/SublimeCodeIntel)
|
||||
* [Theme - Soda](https://github.com/buymeasoda/soda-theme)
|
||||
- [DocBlockr](https://github.com/spadgos/sublime-jsdocs 'DocBlockr on GitHub')
|
||||
- [Drupal API](https://github.com/BrianGilbert/Sublime-Text-2-Goto-Drupal-API)
|
||||
- [LESS](https://github.com/danro/LESS-sublime)
|
||||
- [Package Control](http://wbond.net/sublime_packages/package_control)
|
||||
- [Sublime CodeIntel](http://github.com/Kronuz/SublimeCodeIntel)
|
||||
- [Theme - Soda](https://github.com/buymeasoda/soda-theme)
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
---
|
||||
title: Nginx Redirects With Query String Arguments
|
||||
date: 2017-01-31
|
||||
excerpt: How to redirect from an old domain to a new one, and also to redirect from the root example.com domain to the canonical www subdomain.
|
||||
excerpt:
|
||||
How to redirect from an old domain to a new one, and also to redirect from the
|
||||
root example.com domain to the canonical www subdomain.
|
||||
tags: [nginx]
|
||||
---
|
||||
This is an example of how my Nginx configuration looked to redirect from an old domain to a new one, and also to redirect from the root `example.com` domain to the canonical `www` subdomain.
|
||||
|
||||
This is an example of how my Nginx configuration looked to redirect from an old
|
||||
domain to a new one, and also to redirect from the root `example.com` domain to
|
||||
the canonical `www` subdomain.
|
||||
|
||||
```language-nginx
|
||||
server {
|
||||
|
@ -18,7 +23,12 @@ server {
|
|||
}
|
||||
```
|
||||
|
||||
It also redirects the URI value, e.g. from `http://example.com/test` to `http://example.com/test`, but I noticed recently though that any the query string would be lost - e.g. `http://example.com/?test` would redirect to `http://www.example.com` and the `?test` would be dropped. The application that I built references images based on the query string, so I wanted these to be included within the redirect.
|
||||
It also redirects the URI value, e.g. from `http://example.com/test` to
|
||||
`http://example.com/test`, but I noticed recently though that any the query
|
||||
string would be lost - e.g. `http://example.com/?test` would redirect to
|
||||
`http://www.example.com` and the `?test` would be dropped. The application that
|
||||
I built references images based on the query string, so I wanted these to be
|
||||
included within the redirect.
|
||||
|
||||
This was fixed by making a small change to my `return` statement.
|
||||
|
||||
|
@ -34,7 +44,9 @@ After:
|
|||
return 301 https://www.example.com$uri$is_args$args;
|
||||
```
|
||||
|
||||
`$is_args` is an empty string if there are no arguments, or a `?` to signify the start of the query string. `$args` then adds the arguments (`$query_string` could also be used with the same result).
|
||||
`$is_args` is an empty string if there are no arguments, or a `?` to signify the
|
||||
start of the query string. `$args` then adds the arguments (`$query_string`
|
||||
could also be used with the same result).
|
||||
|
||||
Here is an demo of it working on this website:
|
||||
|
||||
|
|
|
@ -3,46 +3,80 @@ title: Null Users and System Users in Drupal
|
|||
date: 2018-08-16
|
||||
excerpt: Announcing the Null User and System User modules.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-7
|
||||
- drupal-8
|
||||
- drupal-modules
|
||||
- drupal-planet
|
||||
- php
|
||||
- drupal
|
||||
- drupal-7
|
||||
- drupal-8
|
||||
- drupal-modules
|
||||
- drupal-planet
|
||||
- php
|
||||
---
|
||||
Have you ever needed to have a 'special user' to perform tasks on your Drupal site, such as performing actions based on an API request, or for sending an internal site message?
|
||||
|
||||
If you just create a new user, how do you identify that user going forward? Do you hard-code the 'magic' user ID in your custom code? What if the user has a different ID on different environments of your site? You could declare it in each environment’s settings file and retrieve it from there, but what then if you need to do the same on another site? That would mean some duplication of code - and something that could have been abstracted and re-used.
|
||||
Have you ever needed to have a 'special user' to perform tasks on your Drupal
|
||||
site, such as performing actions based on an API request, or for sending an
|
||||
internal site message?
|
||||
|
||||
I had to do this recently, and rather than just duplicate the code I decided to make it into it’s own module - which then became two modules.
|
||||
If you just create a new user, how do you identify that user going forward? Do
|
||||
you hard-code the 'magic' user ID in your custom code? What if the user has a
|
||||
different ID on different environments of your site? You could declare it in
|
||||
each environment’s settings file and retrieve it from there, but what then if
|
||||
you need to do the same on another site? That would mean some duplication of
|
||||
code - and something that could have been abstracted and re-used.
|
||||
|
||||
I had to do this recently, and rather than just duplicate the code I decided to
|
||||
make it into it’s own module - which then became two modules.
|
||||
|
||||
## System users
|
||||
|
||||
The [System User module][1] provides a re-usable, generic way to denote users as 'system users', which is not specific to a certain site or environment as this is value is stored against each individual user in the database.
|
||||
The [System User module][1] provides a re-usable, generic way to denote users as
|
||||
'system users', which is not specific to a certain site or environment as this
|
||||
is value is stored against each individual user in the database.
|
||||
|
||||
'System user' is a term used in Linux, which I thought also applies well to this scenario.
|
||||
'System user' is a term used in Linux, which I thought also applies well to this
|
||||
scenario.
|
||||
|
||||
From <https://www.ssh.com/iam/user/system-account>:
|
||||
|
||||
> A system account is a user account that is created by an operating system during installation and that is used for operating system defined purposes. System accounts often have predefiend user ids. Examples of system accounts include the root account in Linux.
|
||||
> A system account is a user account that is created by an operating system
|
||||
> during installation and that is used for operating system defined purposes.
|
||||
> System accounts often have predefiend user ids. Examples of system accounts
|
||||
> include the root account in Linux.
|
||||
|
||||
A system user isn’t an account that we’d expect a person to log in with and perform routine tasks like updating content, but rather for the system (site) to use to perform tasks like the earlier examples.
|
||||
A system user isn’t an account that we’d expect a person to log in with and
|
||||
perform routine tasks like updating content, but rather for the system (site) to
|
||||
use to perform tasks like the earlier examples.
|
||||
|
||||
### Declaring a user as a system user
|
||||
|
||||
System User module adds a base field to Drupal’s User entity, which determines whether or not each user is a system user - i.e. if this field is `TRUE`, that user is a system user. This means that users can easily be queried to identify which are system users, without having to rely on magic, environment and site specific user IDs. This also means that we can have multiple system users, if needed.
|
||||
System User module adds a base field to Drupal’s User entity, which determines
|
||||
whether or not each user is a system user - i.e. if this field is `TRUE`, that
|
||||
user is a system user. This means that users can easily be queried to identify
|
||||
which are system users, without having to rely on magic, environment and site
|
||||
specific user IDs. This also means that we can have multiple system users, if
|
||||
needed.
|
||||
|
||||
![](/images/blog/null-users-system-users/drupal-8-users-field-data-table.png){.border .p-1}
|
||||
![](/images/blog/null-users-system-users/drupal-8-users-field-data-table.png){.border
|
||||
.p-1}
|
||||
|
||||
In the Drupal 8 version of the module, a `SystemUser` is a custom entity, that contains it’s own `create` method for creating new system users. This is a essentially a wrapper around `User::create()` that automatically sets the value of the system user field as part of the creation.
|
||||
In the Drupal 8 version of the module, a `SystemUser` is a custom entity, that
|
||||
contains it’s own `create` method for creating new system users. This is a
|
||||
essentially a wrapper around `User::create()` that automatically sets the value
|
||||
of the system user field as part of the creation.
|
||||
|
||||
The original intention is that system users would always be created manually in an custom install or update hook, however since releasing the module, I’ve also added an install hook to the module to automatically create a new system user when the module is installed, basing the username on the site name.
|
||||
The original intention is that system users would always be created manually in
|
||||
an custom install or update hook, however since releasing the module, I’ve also
|
||||
added an install hook to the module to automatically create a new system user
|
||||
when the module is installed, basing the username on the site name.
|
||||
|
||||
There is also an open issue to add a Drush command to create a new system user, and I’d imagine I’ll also add a Drupal Console command too.
|
||||
There is also an open issue to add a Drush command to create a new system user,
|
||||
and I’d imagine I’ll also add a Drupal Console command too.
|
||||
|
||||
### Retrieving system users
|
||||
|
||||
Whilst you could easily write your own query that retrieves users based on the value of the system user field, but the module contains a `SystemUserManager` service that contains methods to do so. It also provides a static helper class that determines if a specified user is a system user by checking the value of the system user field.
|
||||
Whilst you could easily write your own query that retrieves users based on the
|
||||
value of the system user field, but the module contains a `SystemUserManager`
|
||||
service that contains methods to do so. It also provides a static helper class
|
||||
that determines if a specified user is a system user by checking the value of
|
||||
the system user field.
|
||||
|
||||
```
|
||||
// Retrieve the first system user.
|
||||
|
@ -52,12 +86,17 @@ $system_user = $this->systemUserManager->getFirst();
|
|||
$is_system_user = SystemUserManager::isSystemUser($user);
|
||||
```
|
||||
|
||||
But what do we return if there are no system users?
|
||||
You could return `NULL` or `FALSE`, but I decided to take a different approach, which became the second module.
|
||||
But what do we return if there are no system users? You could return `NULL` or
|
||||
`FALSE`, but I decided to take a different approach, which became the second
|
||||
module.
|
||||
|
||||
## Null users
|
||||
|
||||
The [Null User module][2] is an implementation of the [null object pattern][3] for users in Drupal 8. In this case, a [NullUser][4] is an extension of Drupal’s `AnonymousUserSession`, which means that it inherits sensible defaults to return for a non-existent User. Though, through inheritance, the `id`, `getRoles` and `hasPermission` methods are overridden to return relevant values.
|
||||
The [Null User module][2] is an implementation of the [null object pattern][3]
|
||||
for users in Drupal 8. In this case, a [NullUser][4] is an extension of Drupal’s
|
||||
`AnonymousUserSession`, which means that it inherits sensible defaults to return
|
||||
for a non-existent User. Though, through inheritance, the `id`, `getRoles` and
|
||||
`hasPermission` methods are overridden to return relevant values.
|
||||
|
||||
```language-php
|
||||
use Drupal\Core\Session\AnonymousUserSession;
|
||||
|
@ -67,7 +106,10 @@ class NullUser extends AnonymousUserSession {
|
|||
}
|
||||
```
|
||||
|
||||
Null User module is a dependency of System User in Drupal 8, so When no system user is found from the `getFirst()` method, a `NullUser` is returned. Whilst I could alternatively have returned `NULL` or `FALSE`, we then would need to check if the returned value was an object or not before calling methods on it.
|
||||
Null User module is a dependency of System User in Drupal 8, so When no system
|
||||
user is found from the `getFirst()` method, a `NullUser` is returned. Whilst I
|
||||
could alternatively have returned `NULL` or `FALSE`, we then would need to check
|
||||
if the returned value was an object or not before calling methods on it.
|
||||
|
||||
```language-php
|
||||
$system_user = $this->systemUserManager->getFirst(); // Returns NULL or FALSE.
|
||||
|
@ -82,7 +124,10 @@ if ($system_user->isActive()) {
|
|||
}
|
||||
```
|
||||
|
||||
Because instead we’re returning a `NullUser`, which through class inheritance has the same methods and properties as a regular user, there is no need to do the additional check as you will always receive a relevant object, and the expected methods will always be present.
|
||||
Because instead we’re returning a `NullUser`, which through class inheritance
|
||||
has the same methods and properties as a regular user, there is no need to do
|
||||
the additional check as you will always receive a relevant object, and the
|
||||
expected methods will always be present.
|
||||
|
||||
```language-php
|
||||
$system_user = $this->systemUserManager->getFirst(); // Returns a NullUser.
|
||||
|
@ -94,7 +139,9 @@ if ($system_user->isActive()) {
|
|||
|
||||
This means we have less code, which also is simpler and more readable.
|
||||
|
||||
System User module is the only one that I’m aware of that makes use of Null User, but I’ve added a list to the [project page][2] so let me know if you can think of any others.
|
||||
System User module is the only one that I’m aware of that makes use of Null
|
||||
User, but I’ve added a list to the [project page][2] so let me know if you can
|
||||
think of any others.
|
||||
|
||||
## Resources
|
||||
|
||||
|
|
|
@ -7,14 +7,17 @@ tags:
|
|||
- mac-os-x
|
||||
- terminal
|
||||
---
|
||||
|
||||
How to open Sublime Text from the command line.
|
||||
|
||||
Paste the following code into the Mac OS X Terminal, assuming that you've installed Sublime Text 2 into the /Applications folder.
|
||||
Paste the following code into the Mac OS X Terminal, assuming that you've
|
||||
installed Sublime Text 2 into the /Applications folder.
|
||||
|
||||
```language-bash
|
||||
$ ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" ~/bin/sublime
|
||||
```
|
||||
|
||||
Now you can type `sublime <filename>` open a file or directory in Sublime Text, or `sublime .` to open the current directory.
|
||||
Now you can type `sublime <filename>` open a file or directory in Sublime Text,
|
||||
or `sublime .` to open the current directory.
|
||||
|
||||
You can also type `sublime --help` to see a list of the available commands.
|
||||
|
|
|
@ -8,9 +8,14 @@ tags:
|
|||
- pantheon
|
||||
- settings.php
|
||||
---
|
||||
I was recently doing some work on a site hosted on [Pantheon](http://getpantheon.com) and came across an issue, for which part of the suggested fix was to ensure that the `$base_url` variable was explicitly defined within settings.php (this is also best practice on all Drupal sites).
|
||||
|
||||
The way that was recommended was by using a `switch()` function based on Pantheon's environment variable. For example:
|
||||
I was recently doing some work on a site hosted on
|
||||
[Pantheon](http://getpantheon.com) and came across an issue, for which part of
|
||||
the suggested fix was to ensure that the `$base_url` variable was explicitly
|
||||
defined within settings.php (this is also best practice on all Drupal sites).
|
||||
|
||||
The way that was recommended was by using a `switch()` function based on
|
||||
Pantheon's environment variable. For example:
|
||||
|
||||
```language-php
|
||||
switch ($_SERVER['PANTHEON_ENVIRONMENT']) {
|
||||
|
@ -33,9 +38,13 @@ switch ($_SERVER['PANTHEON_ENVIRONMENT']) {
|
|||
}
|
||||
```
|
||||
|
||||
Whilst this works, it doesn't conform to the DRY (don't repeat yourself) principle and means that you also might get a rather long and complicated settings file, especially when you start using multiple switches and checking for the value of the environment multiple times.
|
||||
Whilst this works, it doesn't conform to the DRY (don't repeat yourself)
|
||||
principle and means that you also might get a rather long and complicated
|
||||
settings file, especially when you start using multiple switches and checking
|
||||
for the value of the environment multiple times.
|
||||
|
||||
My alternative solution to this is to include an environment-specific settings file.
|
||||
My alternative solution to this is to include an environment-specific settings
|
||||
file.
|
||||
|
||||
To do this, add the following code to the bottom of settings.php:
|
||||
|
||||
|
@ -55,11 +64,20 @@ if (isset($_SERVER['PANTHEON_ENVIRONMENT'])) {
|
|||
}
|
||||
```
|
||||
|
||||
This means that rather than having one long file, each environment has it's own dedicated settings file that contains it's own additional configuration. This is much easier to read and make changes to, and also means that less code is loaded and parsed by PHP. Settings that apply to all environments are still added to settings.php.
|
||||
This means that rather than having one long file, each environment has it's own
|
||||
dedicated settings file that contains it's own additional configuration. This is
|
||||
much easier to read and make changes to, and also means that less code is loaded
|
||||
and parsed by PHP. Settings that apply to all environments are still added to
|
||||
settings.php.
|
||||
|
||||
Below this, I also include a [similar piece of code](/blog/include-local-drupal-settings-file-environment-configuration-and-overrides/) to include a settings.local.php file. The settings.php file then gets committed into the [Git](http://git-scm.com) repository.
|
||||
Below this, I also include a
|
||||
[similar piece of code](/blog/include-local-drupal-settings-file-environment-configuration-and-overrides/)
|
||||
to include a settings.local.php file. The settings.php file then gets committed
|
||||
into the [Git](http://git-scm.com) repository.
|
||||
|
||||
Within the sites/default directory, I also include an example file (example.settings.env.php) for reference. This is duplicated, renamed and populated accordingly.
|
||||
Within the sites/default directory, I also include an example file
|
||||
(example.settings.env.php) for reference. This is duplicated, renamed and
|
||||
populated accordingly.
|
||||
|
||||
```language-php
|
||||
<?php
|
||||
|
@ -78,4 +96,5 @@ Within the sites/default directory, I also include an example file (example.sett
|
|||
$base_url = '';
|
||||
```
|
||||
|
||||
The environment specific files are also committed into Git and pushed to Pantheon, and are then included automatically on each environment.
|
||||
The environment specific files are also committed into Git and pushed to
|
||||
Pantheon, and are then included automatically on each environment.
|
||||
|
|
|
@ -1,18 +1,30 @@
|
|||
---
|
||||
title: How to put your PHP application in a subdirectory of another site with Nginx
|
||||
title:
|
||||
How to put your PHP application in a subdirectory of another site with Nginx
|
||||
date: 2018-03-12
|
||||
excerpt: How to configure Nginx to serve a PHP application from within a subdirectory of another.
|
||||
excerpt:
|
||||
How to configure Nginx to serve a PHP application from within a subdirectory
|
||||
of another.
|
||||
tags:
|
||||
- nginx
|
||||
- php
|
||||
- nginx
|
||||
- php
|
||||
---
|
||||
In January, [Chris Fidao][0] posted a video to [Servers for Hackers][1] showing how to put different PHP applications in different subdirectories and have them serving on different paths with Nginx. I’ve had to do this a few times previously, and it’s great to have this video as a reference.
|
||||
|
||||
> In this video, we work through how to put your PHP application in a subdirectory of another site.
|
||||
In January, [Chris Fidao][0] posted a video to [Servers for Hackers][1] showing
|
||||
how to put different PHP applications in different subdirectories and have them
|
||||
serving on different paths with Nginx. I’ve had to do this a few times
|
||||
previously, and it’s great to have this video as a reference.
|
||||
|
||||
> In this video, we work through how to put your PHP application in a
|
||||
> subdirectory of another site.
|
||||
>
|
||||
> For example, we may have an application running at example.org but need a second application running at example.org/blog.
|
||||
> For example, we may have an application running at example.org but need a
|
||||
> second application running at example.org/blog.
|
||||
>
|
||||
> This feels like it should be simple, but it turns out to be more complex and fraught with confusing Nginx configurations! To make matter worse (or, perhaps, to illustrate this point), a quick Google search reveals a TON of confusing, non-working examples.
|
||||
> This feels like it should be simple, but it turns out to be more complex and
|
||||
> fraught with confusing Nginx configurations! To make matter worse (or,
|
||||
> perhaps, to illustrate this point), a quick Google search reveals a TON of
|
||||
> confusing, non-working examples.
|
||||
|
||||
<https://serversforhackers.com/c/nginx-php-in-subdirectory>
|
||||
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
---
|
||||
title: Prevent Apache from displaying text files within a web browser
|
||||
date: 2012-05-23
|
||||
excerpt: How to prevent Apache from displaying the contents of files like CHANGELOG.txt.
|
||||
excerpt:
|
||||
How to prevent Apache from displaying the contents of files like
|
||||
CHANGELOG.txt.
|
||||
tags:
|
||||
- apache
|
||||
- code
|
||||
- drupal
|
||||
---
|
||||
When you download [Drupal](http://drupal.org/project/drupal), there are several text files that are placed in the root of your installation. You don't want or need these to be visible to anyone attempting to view them in a browser - especially CHANGELOG.txt as that includes the exact version of Drupal you are running and could therefore have security implications.
|
||||
|
||||
Rather than delete these files or change the file permissions manually for each file, I can add the following lines into my VirtualHost configuration.
|
||||
When you download [Drupal](http://drupal.org/project/drupal), there are several
|
||||
text files that are placed in the root of your installation. You don't want or
|
||||
need these to be visible to anyone attempting to view them in a browser -
|
||||
especially CHANGELOG.txt as that includes the exact version of Drupal you are
|
||||
running and could therefore have security implications.
|
||||
|
||||
Rather than delete these files or change the file permissions manually for each
|
||||
file, I can add the following lines into my VirtualHost configuration.
|
||||
|
||||
```language-apacheconf
|
||||
<Files ~ "\.txt$">
|
||||
|
@ -18,4 +26,5 @@ Rather than delete these files or change the file permissions manually for each
|
|||
</Files>
|
||||
```
|
||||
|
||||
This prevents any files with a .txt extension from being accessed and rendered in a web browser.
|
||||
This prevents any files with a .txt extension from being accessed and rendered
|
||||
in a web browser.
|
||||
|
|
|
@ -5,6 +5,16 @@ excerpt: I’m moving jobs.
|
|||
tags:
|
||||
- personal
|
||||
---
|
||||
2 weeks ago, I handed in my notice of resignation to [Horse & Country TV](http://horseandcountry.tv)because I've been offered a new role at [Proctor & Stevenson](http://proctors.co.uk) - a Marketing Design and Communications agency in Bristol.
|
||||
|
||||
Proctors have an [extensive client list](http://www.proctors.co.uk/clients) - including [BMW](http://www.proctors.co.uk/clients/bmw-financial-services), [Panasonic](http://www.proctors.co.uk/clients/panasonic), the [Open University](http://www.proctors.co.uk/clients/open-university) and [VOSA](http://www.proctors.co.uk/clients/vosa), and it's going to be a fantastic opportunity for me to continue expanding my skillset whilst gaining vital experience.
|
||||
2 weeks ago, I handed in my notice of resignation to
|
||||
[Horse & Country TV](http://horseandcountry.tv)because I've been offered a new
|
||||
role at [Proctor & Stevenson](http://proctors.co.uk) - a Marketing Design and
|
||||
Communications agency in Bristol.
|
||||
|
||||
Proctors have an [extensive client list](http://www.proctors.co.uk/clients) -
|
||||
including [BMW](http://www.proctors.co.uk/clients/bmw-financial-services),
|
||||
[Panasonic](http://www.proctors.co.uk/clients/panasonic), the
|
||||
[Open University](http://www.proctors.co.uk/clients/open-university) and
|
||||
[VOSA](http://www.proctors.co.uk/clients/vosa), and it's going to be a fantastic
|
||||
opportunity for me to continue expanding my skillset whilst gaining vital
|
||||
experience.
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
---
|
||||
title: Proctors Hosting the next Drupal Meetup
|
||||
date: 2011-05-20
|
||||
excerpt: Proctor & Stevenson are going to be hosting the next Bristol & South West Drupal meetup.
|
||||
excerpt:
|
||||
Proctor & Stevenson are going to be hosting the next Bristol & South West
|
||||
Drupal meetup.
|
||||
tags:
|
||||
- meetups
|
||||
- drupal-bristol
|
||||
---
|
||||
My employer, [Proctor & Stevenson](http://www.proctors.co.uk), are going to be hosting the next Bristol & South West Drupal meetup on the 25th May at our offices.
|
||||
|
||||
You can [view more details](http://groups.drupal.org/node/147324), or register [on our website](http://www.proctors.co.uk/Drupal-SWUG-Meetup).
|
||||
My employer, [Proctor & Stevenson](http://www.proctors.co.uk), are going to be
|
||||
hosting the next Bristol & South West Drupal meetup on the 25th May at our
|
||||
offices.
|
||||
|
||||
You can [view more details](http://groups.drupal.org/node/147324), or register
|
||||
[on our website](http://www.proctors.co.uk/Drupal-SWUG-Meetup).
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
---
|
||||
title: Using PSR-4 Autoloading for your Drupal 7 Test Cases
|
||||
excerpt: How to use the PSR-4 autoloading standard for Drupal 7 Simpletest test cases.
|
||||
excerpt:
|
||||
How to use the PSR-4 autoloading standard for Drupal 7 Simpletest test cases.
|
||||
tags: [drupal, drupal-planet, drupal-7, testing, simpletest, php, psr]
|
||||
date: 2020-02-04
|
||||
---
|
||||
|
||||
<p>{{ page.excerpt }}</p>
|
||||
|
||||
## The Traditional Way
|
||||
|
||||
The typical way of including test cases in Drupal 7 is to add one or more classes within a `.test` file - e.g. `opdavies.test`.
|
||||
This would typically include all of the different test cases for that module, and would be placed in the root of the module’s directory alongside the `.info` and `.module` files.
|
||||
The typical way of including test cases in Drupal 7 is to add one or more
|
||||
classes within a `.test` file - e.g. `opdavies.test`. This would typically
|
||||
include all of the different test cases for that module, and would be placed in
|
||||
the root of the module’s directory alongside the `.info` and `.module` files.
|
||||
|
||||
In order to load the files, each file would need to be declared within the `.info` file for the module.
|
||||
In order to load the files, each file would need to be declared within the
|
||||
`.info` file for the module.
|
||||
|
||||
There is a convention that if you have multiple tests for your project, these can be split into different files and grouped within a `tests` directory.
|
||||
There is a convention that if you have multiple tests for your project, these
|
||||
can be split into different files and grouped within a `tests` directory.
|
||||
|
||||
```ini
|
||||
; Load a test file at the root of the module
|
||||
|
@ -26,10 +32,11 @@ files[] = tests/bar.test
|
|||
|
||||
## Using the xautoload Module
|
||||
|
||||
Whilst splitting tests into separate files makes things more organised, each file needs to be loaded separately.
|
||||
This can be made simpler by using the [Xautoload module][], which supports wildcards when declaring files.
|
||||
Whilst splitting tests into separate files makes things more organised, each
|
||||
file needs to be loaded separately. This can be made simpler by using the
|
||||
[Xautoload module][], which supports wildcards when declaring files.
|
||||
|
||||
[Xautoload module]: https://www.drupal.org/project/xautoload
|
||||
[xautoload module]: https://www.drupal.org/project/xautoload
|
||||
|
||||
```ini
|
||||
files[] = tests/**/*.test
|
||||
|
@ -41,10 +48,15 @@ This would load all of the `.test` files within the tests directory.
|
|||
|
||||
Another option is to use PSR-4 (or PSR-0) autoloading.
|
||||
|
||||
This should be a lot more familiar to those who have worked with Drupal 8, Symfony etc, and means that each test case is in its own file which is cleaner, files have the `.php` extension which is more standard, and the name of the file matches the name of the test class for consistency.
|
||||
This should be a lot more familiar to those who have worked with Drupal 8,
|
||||
Symfony etc, and means that each test case is in its own file which is cleaner,
|
||||
files have the `.php` extension which is more standard, and the name of the file
|
||||
matches the name of the test class for consistency.
|
||||
|
||||
To do this, create a `src/Tests` (PSR-4) or `lib/Drupal/{module_name}/Tests` (PSR-0) directory within your module, and then add or move your test cases there.
|
||||
Add the appropriate namespace for your module, and ensure that `DrupalWebTestCase` or `DrupalUnitTestCase` is also namespaced.
|
||||
To do this, create a `src/Tests` (PSR-4) or `lib/Drupal/{module_name}/Tests`
|
||||
(PSR-0) directory within your module, and then add or move your test cases
|
||||
there. Add the appropriate namespace for your module, and ensure that
|
||||
`DrupalWebTestCase` or `DrupalUnitTestCase` is also namespaced.
|
||||
|
||||
```php
|
||||
// src/Tests/Functional/OliverDaviesTest.php
|
||||
|
@ -56,11 +68,14 @@ class OliverDaviesTest extends \DrupalWebTestCase {
|
|||
}
|
||||
```
|
||||
|
||||
This also supports subdirectories, so you can group classes within `Functional` and `Unit` directories if you like.
|
||||
This also supports subdirectories, so you can group classes within `Functional`
|
||||
and `Unit` directories if you like.
|
||||
|
||||
If you want to see an real-world example, see the Drupal 7 branch of the [Override Node Options module][override_node_options].
|
||||
If you want to see an real-world example, see the Drupal 7 branch of the
|
||||
[Override Node Options module][override_node_options].
|
||||
|
||||
[override_node_options]: https://git.drupalcode.org/project/override_node_options/tree/7.x-1.x
|
||||
[override_node_options]:
|
||||
https://git.drupalcode.org/project/override_node_options/tree/7.x-1.x
|
||||
|
||||
### Digging into the simpletest_test_get_all function
|
||||
|
||||
|
@ -104,13 +119,18 @@ foreach (array(
|
|||
}
|
||||
```
|
||||
|
||||
It looks for a the tests directory (`src/Tests` or `lib/Drupal/{module_name}/Tests`) within the module, and then finds any `.php` files within it. It then converts the file name into the fully qualified (namespaced) class name and loads it automatically.
|
||||
It looks for a the tests directory (`src/Tests` or
|
||||
`lib/Drupal/{module_name}/Tests`) within the module, and then finds any `.php`
|
||||
files within it. It then converts the file name into the fully qualified
|
||||
(namespaced) class name and loads it automatically.
|
||||
|
||||
### Running the Tests
|
||||
|
||||
You can still run the tests from within the Simpletest UI, or from the command line using `run-tests.sh`.
|
||||
You can still run the tests from within the Simpletest UI, or from the command
|
||||
line using `run-tests.sh`.
|
||||
|
||||
If you want to run a specific test case using the `--class` option, you will now need to include the fully qualified name.
|
||||
If you want to run a specific test case using the `--class` option, you will now
|
||||
need to include the fully qualified name.
|
||||
|
||||
```
|
||||
php scripts/run-tests.sh --class Drupal\\opdavies\\Tests\\Functional\\OliverDaviesTest
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
---
|
||||
title: Published my first NPM package
|
||||
date: 2018-12-16
|
||||
excerpt: Yesterday I published my first module onto NPM, and it’s a plugin for Tailwind CSS to be used alongside Vue.js.
|
||||
excerpt:
|
||||
Yesterday I published my first module onto NPM, and it’s a plugin for Tailwind
|
||||
CSS to be used alongside Vue.js.
|
||||
tags:
|
||||
- npm
|
||||
- tailwind-css
|
||||
- vuejs
|
||||
- npm
|
||||
- tailwind-css
|
||||
- vuejs
|
||||
---
|
||||
Yesterday I published my first module onto NPM, and it’s a plugin for [Tailwind CSS][tailwind] to be used alongside [Vue.js](https://vuejs.org).
|
||||
|
||||
The plugin adds classes for showing and hiding elements in different display variations in combination with Vue's [v-cloak directive](https://vuejs.org/v2/api/#v-cloak), which I originally saw in [the first 'Building Kitetail' video](https://youtu.be/XUXpcbYQ_iQ?t=2360). These are useful for when you want an element to be visible whilst Vue is compiling, and hidden afterwards.
|
||||
Yesterday I published my first module onto NPM, and it’s a plugin for [Tailwind
|
||||
CSS][tailwind] to be used alongside [Vue.js](https://vuejs.org).
|
||||
|
||||
The plugin adds classes for showing and hiding elements in different display
|
||||
variations in combination with Vue's
|
||||
[v-cloak directive](https://vuejs.org/v2/api/#v-cloak), which I originally saw
|
||||
in [the first 'Building Kitetail' video](https://youtu.be/XUXpcbYQ_iQ?t=2360).
|
||||
These are useful for when you want an element to be visible whilst Vue is
|
||||
compiling, and hidden afterwards.
|
||||
|
||||
Here is the compiled CSS that is added by the plugin:
|
||||
|
||||
|
@ -51,11 +60,16 @@ Here is the compiled CSS that is added by the plugin:
|
|||
}
|
||||
```
|
||||
|
||||
The `v-cloak` directive exists on an element until Vue finishes compiling, after which it is removed. Therefore adding a `v-cloak-block` class to an element will make it `display: block` whilst Vue is compiling and the element is cloaked, and `display: none` afterwards when the Vue markup is compiled and rendered.
|
||||
The `v-cloak` directive exists on an element until Vue finishes compiling, after
|
||||
which it is removed. Therefore adding a `v-cloak-block` class to an element will
|
||||
make it `display: block` whilst Vue is compiling and the element is cloaked, and
|
||||
`display: none` afterwards when the Vue markup is compiled and rendered.
|
||||
|
||||
In my `base.html.twig` template, I’ve added `v-cloak` to the wrapper div within the `body`.
|
||||
In my `base.html.twig` template, I’ve added `v-cloak` to the wrapper div within
|
||||
the `body`.
|
||||
|
||||
{% verbatim %}<div v-pre markdown="1">
|
||||
|
||||
```twig
|
||||
<body class="font-sans leading-normal">
|
||||
<div id="app" v-cloak>
|
||||
|
@ -63,11 +77,16 @@ In my `base.html.twig` template, I’ve added `v-cloak` to the wrapper div withi
|
|||
</div>
|
||||
</body>
|
||||
```
|
||||
|
||||
</div>{% endverbatim %}
|
||||
|
||||
Within my `navbar.html.twig` partial, I have a placeholder div that also contains the site name, which is instantly visible but has the `v-cloak-block` class so it’s hidden once Vue has compiled and the `Navbar` Vue component is visible instead.
|
||||
Within my `navbar.html.twig` partial, I have a placeholder div that also
|
||||
contains the site name, which is instantly visible but has the `v-cloak-block`
|
||||
class so it’s hidden once Vue has compiled and the `Navbar` Vue component is
|
||||
visible instead.
|
||||
|
||||
{% verbatim %}<div v-pre markdown="1">
|
||||
|
||||
```twig
|
||||
<div class="border-bottom border-b border-gray-300 mb-6">
|
||||
<div class="container mx-auto">
|
||||
|
@ -82,11 +101,18 @@ Within my `navbar.html.twig` partial, I have a placeholder div that also contain
|
|||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
</div>{% endverbatim %}
|
||||
|
||||
I was originally surprised that these classes weren’t included as part of Tailwind or as part of an existing plugin, but as I’ve already used these styles on several projects that include Vue.js with Symfony or Sculpin, it made sense to extract it into a plugin and make it available as a npm package which I can easily add to any project - as well as making it easier to maintain if I need to add additional variations at a later point.
|
||||
I was originally surprised that these classes weren’t included as part of
|
||||
Tailwind or as part of an existing plugin, but as I’ve already used these styles
|
||||
on several projects that include Vue.js with Symfony or Sculpin, it made sense
|
||||
to extract it into a plugin and make it available as a npm package which I can
|
||||
easily add to any project - as well as making it easier to maintain if I need to
|
||||
add additional variations at a later point.
|
||||
|
||||
**You can view [the package on npmjs.com][npm], and [the code repository on GitHub][github].**
|
||||
**You can view [the package on npmjs.com][npm], and [the code repository on
|
||||
GitHub][github].**
|
||||
|
||||
[github]: https://github.com/opdavies/tailwindcss-vuejs
|
||||
[npm]: https://www.npmjs.com/package/tailwindcss-vuejs
|
||||
|
|
|
@ -4,32 +4,45 @@ date: 2017-07-13
|
|||
excerpt: How I moved my website to GitHub pages.
|
||||
tags: [sculpin, php, github]
|
||||
meta:
|
||||
image:
|
||||
url: '/images/blog/jackson-octocat.png'
|
||||
type: 'image/png'
|
||||
height: 200
|
||||
width: 451
|
||||
image:
|
||||
url: '/images/blog/jackson-octocat.png'
|
||||
type: 'image/png'
|
||||
height: 200
|
||||
width: 451
|
||||
---
|
||||
|
||||
<p class="text-center" markdown="1">![](/images/blog/jackson-octocat.png)</p>
|
||||
|
||||
Earlier this week I moved this site from my personal Linode server to [GitHub Pages][0].
|
||||
Earlier this week I moved this site from my personal Linode server to [GitHub
|
||||
Pages][0].
|
||||
|
||||
This made sense as I already kept the source code in [on GitHub][1], the issue was that GitHub Pages doesn’t know how to dynamically parse and generate a Sculpin site like it does with some other static site generators. It can though parse and serve HTML files, which is what Sculpin generates. It’s just a case of how those files are added to GitHub.
|
||||
This made sense as I already kept the source code in [on GitHub][1], the issue
|
||||
was that GitHub Pages doesn’t know how to dynamically parse and generate a
|
||||
Sculpin site like it does with some other static site generators. It can though
|
||||
parse and serve HTML files, which is what Sculpin generates. It’s just a case of
|
||||
how those files are added to GitHub.
|
||||
|
||||
I’ve seen different implementations of this, mostly where the Sculpin code is on one branch, and the generated HTML code is on a separate `gh-pages` or `master` branch (depending on your repository name). I’m not fond of this approach as it means automatically checking out and merging branches which can get messy, and also it’s weird to look at a repo’s branches page and see one branch maybe tens or hundreds of commits both ahead and behind the default branch.
|
||||
I’ve seen different implementations of this, mostly where the Sculpin code is on
|
||||
one branch, and the generated HTML code is on a separate `gh-pages` or `master`
|
||||
branch (depending on your repository name). I’m not fond of this approach as it
|
||||
means automatically checking out and merging branches which can get messy, and
|
||||
also it’s weird to look at a repo’s branches page and see one branch maybe tens
|
||||
or hundreds of commits both ahead and behind the default branch.
|
||||
|
||||
This has been made simpler and tidier now that we can use a `docs` directory within the repository to serve content.
|
||||
This has been made simpler and tidier now that we can use a `docs` directory
|
||||
within the repository to serve content.
|
||||
|
||||
<img src="/images/blog/github-pages.png" alt="" class="is-centered"
|
||||
style="margin-top: 20px; margin-bottom: 20px"
|
||||
|
||||
<img
|
||||
src="/images/blog/github-pages.png"
|
||||
alt=""
|
||||
class="is-centered"
|
||||
style="margin-top: 20px; margin-bottom: 20px"
|
||||
>
|
||||
|
||||
This means that I can simply re-generate the site after making changes and add it as an additional commit to my main branch with no need to switch branches or perform a merge.
|
||||
This means that I can simply re-generate the site after making changes and add
|
||||
it as an additional commit to my main branch with no need to switch branches or
|
||||
perform a merge.
|
||||
|
||||
To simplify this, I’ve added a new [publish.sh script][3] into my repository to automate the sites. This is how it currently looks:
|
||||
To simplify this, I’ve added a new [publish.sh script][3] into my repository to
|
||||
automate the sites. This is how it currently looks:
|
||||
|
||||
```language-bash
|
||||
#!/usr/bin/env bash
|
||||
|
@ -53,30 +66,43 @@ git commit -m 'Build.'
|
|||
git push origin HEAD
|
||||
```
|
||||
|
||||
This begins by removing the deleting the existing `docs` directory and re-generating the site with the specified environment. Then I add a `.nojekyll` file and rename the output directory to replace `docs`.
|
||||
This begins by removing the deleting the existing `docs` directory and
|
||||
re-generating the site with the specified environment. Then I add a `.nojekyll`
|
||||
file and rename the output directory to replace `docs`.
|
||||
|
||||
Now the changes can be added, committed and pushed. Once pushed, the new code is automatically served by GitHub Pages.
|
||||
Now the changes can be added, committed and pushed. Once pushed, the new code is
|
||||
automatically served by GitHub Pages.
|
||||
|
||||
## HTTPS
|
||||
|
||||
GitHub Pages unfortunately does [not support HTTPS for custom domains][7].
|
||||
|
||||
As the site was previously using HTTPS, I didn’t want to have to go back to HTTP, break any incoming links and lose any potential traffic. To continue using HTTPS, I decided to [use Cloudflare][6] to serve the site via their CDN which does allow for HTTPS traffic.
|
||||
As the site was previously using HTTPS, I didn’t want to have to go back to
|
||||
HTTP, break any incoming links and lose any potential traffic. To continue using
|
||||
HTTPS, I decided to [use Cloudflare][6] to serve the site via their CDN which
|
||||
does allow for HTTPS traffic.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Enable automatically running `publish.sh` when new changes are pushed to GitHub rather than running it manually. I was previously [using Jenkins][4] and Fabric for this, though I’m also going to look into using Travis to accomplish this.
|
||||
- Add the pre-build steps such as running `composer install` and `yarn` to install dependencies, and `gulp` to create the front-end assets. This was previously done by Jenkins in my previous setup.
|
||||
- Enable automatically running `publish.sh` when new changes are pushed to
|
||||
GitHub rather than running it manually. I was previously [using Jenkins][4]
|
||||
and Fabric for this, though I’m also going to look into using Travis to
|
||||
accomplish this.
|
||||
- Add the pre-build steps such as running `composer install` and `yarn` to
|
||||
install dependencies, and `gulp` to create the front-end assets. This was
|
||||
previously done by Jenkins in my previous setup.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Publishing your GitHub Pages site from a /docs folder on your master branch][2]
|
||||
- [Publishing your GitHub Pages site from a /docs folder on your master
|
||||
branch][2]
|
||||
- [Bypassing Jekyll on GitHub Pages][5]
|
||||
- [Secure and fast GitHub Pages with CloudFlare][6]
|
||||
|
||||
[0]: https://pages.github.com
|
||||
[1]: https://github.com/opdavies/oliverdavies.uk
|
||||
[2]: https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/#publishing-your-github-pages-site-from-a-docs-folder-on-your-master-branch
|
||||
[2]:
|
||||
https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/#publishing-your-github-pages-site-from-a-docs-folder-on-your-master-branch
|
||||
[3]: https://github.com/opdavies/oliverdavies.uk/blob/master/publish.sh
|
||||
[4]: /articles/2015/07/21/automating-sculpin-jenkins
|
||||
[5]: https://github.com/blog/572-bypassing-jekyll-on-github-pages
|
||||
|
|
|
@ -3,21 +3,32 @@ title: Queuing Private Messages in Drupal 8
|
|||
date: 2018-02-27
|
||||
excerpt: Introducing the Private Message Queue module for Drupal 8.
|
||||
tags:
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-modules
|
||||
- drupal-planet
|
||||
- open-source
|
||||
- drupal
|
||||
- drupal-8
|
||||
- drupal-modules
|
||||
- drupal-planet
|
||||
- open-source
|
||||
---
|
||||
My current project at [Microserve][0] is a Drupal 8 website that uses the [Private Message][1] module for users to send messages to each other.
|
||||
|
||||
In some cases though, the threads could contain hundreds of recipients so I decided that it would be good to queue the message requests so that they can be processed as part of a background process for better performance. The Private Message module does not include this, so I've written and released a separate [Private Message Queue][2] module.
|
||||
My current project at [Microserve][0] is a Drupal 8 website that uses the
|
||||
[Private Message][1] module for users to send messages to each other.
|
||||
|
||||
In some cases though, the threads could contain hundreds of recipients so I
|
||||
decided that it would be good to queue the message requests so that they can be
|
||||
processed as part of a background process for better performance. The Private
|
||||
Message module does not include this, so I've written and released a separate
|
||||
[Private Message Queue][2] module.
|
||||
|
||||
## Queuing a Message
|
||||
|
||||
The module provices a `PrivateMessageQueuer` service (`private_message_queue.queuer`) which queues the items via the `queue()` method.
|
||||
The module provices a `PrivateMessageQueuer` service
|
||||
(`private_message_queue.queuer`) which queues the items via the `queue()`
|
||||
method.
|
||||
|
||||
The method accepts an array of `User` objects as the messsage recipients, the message body text and another user as the message owner. (I’m currently considering [whether to make the owner optional][4], and default to the current user if one is not specified)
|
||||
The method accepts an array of `User` objects as the messsage recipients, the
|
||||
message body text and another user as the message owner. (I’m currently
|
||||
considering [whether to make the owner optional][4], and default to the current
|
||||
user if one is not specified)
|
||||
|
||||
Here is an example:
|
||||
|
||||
|
@ -30,7 +41,9 @@ $queuer = \Drupal::service('private_message_queue.queuer');
|
|||
$queuer->queue($recipients, $message, $owner);
|
||||
```
|
||||
|
||||
These three pieces of data are then saved as part of the queued item. You can see these by checking the "queue" table in the database or by running `drush queue-list`.
|
||||
These three pieces of data are then saved as part of the queued item. You can
|
||||
see these by checking the "queue" table in the database or by running
|
||||
`drush queue-list`.
|
||||
|
||||
![](/images/blog/private-message-queue.png)
|
||||
|
||||
|
@ -42,13 +55,22 @@ private_message_queue 19 Drupal\Core\Queue\DatabaseQueue
|
|||
|
||||
## Processing the Queue
|
||||
|
||||
The module also provides a `PrivateMessageQueue` queue worker, which processes the queued items. For each item, it creates a new private message setting the owner and the message body.
|
||||
The module also provides a `PrivateMessageQueue` queue worker, which processes
|
||||
the queued items. For each item, it creates a new private message setting the
|
||||
owner and the message body.
|
||||
|
||||
It uses the `PrivateMessageThread` class from the Private Message module to find for an existing thread for the specified recipients, or creates a new thread if one isn't found. The new message is then added to the thread.
|
||||
It uses the `PrivateMessageThread` class from the Private Message module to find
|
||||
for an existing thread for the specified recipients, or creates a new thread if
|
||||
one isn't found. The new message is then added to the thread.
|
||||
|
||||
The queue is processed on each cron run, so I recommend adding a module like [Ultimate Cron][3] so that you can process the queued items frequently (e.g. every 15 minutes) and run the heavier tasks like checking for updates etc less frequently (e.g. once a day).
|
||||
The queue is processed on each cron run, so I recommend adding a module like
|
||||
[Ultimate Cron][3] so that you can process the queued items frequently (e.g.
|
||||
every 15 minutes) and run the heavier tasks like checking for updates etc less
|
||||
frequently (e.g. once a day).
|
||||
|
||||
You can also process the queue manually with Drush using the `drush queue-run <queue-name>` command - e.g. `drush queue-run private_message_queue`.
|
||||
You can also process the queue manually with Drush using the
|
||||
`drush queue-run <queue-name>` command - e.g.
|
||||
`drush queue-run private_message_queue`.
|
||||
|
||||
```
|
||||
$ drush queue-run private_message_queue
|
||||
|
|
|
@ -3,43 +3,65 @@ title: Quick Project Switching in PhpStorm
|
|||
date: 2018-09-04
|
||||
excerpt: How to quickly switch between projects in PhpStorm.
|
||||
tags:
|
||||
- phpstorm
|
||||
- phpstorm
|
||||
has_tweets: true
|
||||
---
|
||||
Following a recent conversation on Twitter with [socketwench](https://twitter.com/socketwench) about project switching in PhpStorm, I thought I’d document my workflow here.
|
||||
|
||||
Here is the original tweet and my initial response. I also have a lot of PhpStorm projects, and as I’m always working on multiple projects I regularly need to switch between them.
|
||||
Following a recent conversation on Twitter with
|
||||
[socketwench](https://twitter.com/socketwench) about project switching in
|
||||
PhpStorm, I thought I’d document my workflow here.
|
||||
|
||||
Here is the original tweet and my initial response. I also have a lot of
|
||||
PhpStorm projects, and as I’m always working on multiple projects I regularly
|
||||
need to switch between them.
|
||||
|
||||
{% include 'tweet' with {
|
||||
content: '<p lang="en" dir="ltr">I think you can start typing and it will filter?</p>— Oliver Davies (@opdavies) <a href="https://twitter.com/opdavies/status/1034472920532365312?ref_src=twsrc%5Etfw">August 28, 2018</a>',
|
||||
} %}
|
||||
|
||||
On the PhpStorm welcome screen that displays when you first open it, your recent projects are displayed on the left-hand side of the screen, and are filterable. That means that I can start typing a project name, e.g. `oli`, and I will only see projects that start with that input.
|
||||
On the PhpStorm welcome screen that displays when you first open it, your recent
|
||||
projects are displayed on the left-hand side of the screen, and are filterable.
|
||||
That means that I can start typing a project name, e.g. `oli`, and I will only
|
||||
see projects that start with that input.
|
||||
|
||||
![The PhpStorm welcome screen with filters applied to the project list](/images/blog/quick-project-switching-phpstorm/welcome-screen.png){.with-border .with-padding}
|
||||
![The PhpStorm welcome screen with filters applied to the project list](/images/blog/quick-project-switching-phpstorm/welcome-screen.png){.with-border
|
||||
.with-padding}
|
||||
|
||||
That’s great when opening a project from scratch, but what about when we’re already within a project and just want to be able to switch to another?
|
||||
That’s great when opening a project from scratch, but what about when we’re
|
||||
already within a project and just want to be able to switch to another?
|
||||
|
||||
{% include 'tweet' with {
|
||||
content: '<p lang="en" dir="ltr">You can also use 'Open recent' within the actions list, and then filter the list of projects. <a href="https://t.co/k8G9iIQNP0">pic.twitter.com/k8G9iIQNP0</a></p>— Oliver Davies (@opdavies) <a href="https://twitter.com/opdavies/status/1034542753651281920?ref_src=twsrc%5Etfw">August 28, 2018</a>',
|
||||
} %}
|
||||
|
||||
There’s also a way to access this list once PhpStorm is open, by clicking 'Open Recent' within the File menu. The issue here though is that this list is not filterable.
|
||||
There’s also a way to access this list once PhpStorm is open, by clicking 'Open
|
||||
Recent' within the File menu. The issue here though is that this list is not
|
||||
filterable.
|
||||
|
||||
You can also access this list using the keyboard, though the 'Search everywhere' or 'Find action' panes, and these are filterable.
|
||||
You can also access this list using the keyboard, though the 'Search everywhere'
|
||||
or 'Find action' panes, and these are filterable.
|
||||
|
||||
![Using the 'find action' pane to find 'Open Recent'](/images/blog/quick-project-switching-phpstorm/find-action.png){.with-border .with-padding}
|
||||
![Using the 'find action' pane to find 'Open Recent'](/images/blog/quick-project-switching-phpstorm/find-action.png){.with-border
|
||||
.with-padding}
|
||||
|
||||
Once the 'Open Recent' option is selected, you see the same project list as on the welcome screen, which is filtered in the same way by starting to type potential project names.
|
||||
Once the 'Open Recent' option is selected, you see the same project list as on
|
||||
the welcome screen, which is filtered in the same way by starting to type
|
||||
potential project names.
|
||||
|
||||
![The filtered project list](/images/blog/quick-project-switching-phpstorm/open-recent.png){.with-border .with-padding}
|
||||
![The filtered project list](/images/blog/quick-project-switching-phpstorm/open-recent.png){.with-border
|
||||
.with-padding}
|
||||
|
||||
## Adding a Keyboard Shortcut
|
||||
|
||||
We can make this easier by adding a new keyboard shortcut. Within the Keymap preferences, you can search for 'Open Recent' and right-click it to add a new keyboard shortcut and define the key combination.
|
||||
We can make this easier by adding a new keyboard shortcut. Within the Keymap
|
||||
preferences, you can search for 'Open Recent' and right-click it to add a new
|
||||
keyboard shortcut and define the key combination.
|
||||
|
||||
![Finding the 'Open Recent' shortcut in the Keymap preferences](/images/blog/quick-project-switching-phpstorm/adding-keyboard-shortcut-1.png){.with-border .with-padding}
|
||||
![Finding the 'Open Recent' shortcut in the Keymap preferences](/images/blog/quick-project-switching-phpstorm/adding-keyboard-shortcut-1.png){.with-border
|
||||
.with-padding}
|
||||
|
||||
![Assigning a keyboard shortcut](/images/blog/quick-project-switching-phpstorm/adding-keyboard-shortcut-2.png){.with-border .with-padding}
|
||||
![Assigning a keyboard shortcut](/images/blog/quick-project-switching-phpstorm/adding-keyboard-shortcut-2.png){.with-border
|
||||
.with-padding}
|
||||
|
||||
This this shortcut added, you can now use it to instantly bring up your recent projects list, filter it and switch project.
|
||||
This this shortcut added, you can now use it to instantly bring up your recent
|
||||
projects list, filter it and switch project.
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
---
|
||||
title: The Quickest way to Install Sublime Text 2 in Ubuntu
|
||||
date: 2013-03-02
|
||||
excerpt: After reading numerous blog posts about how to install Sublime Text 2 in Ubuntu, this is definitely the quickest way!
|
||||
excerpt:
|
||||
After reading numerous blog posts about how to install Sublime Text 2 in
|
||||
Ubuntu, this is definitely the quickest way!
|
||||
tags:
|
||||
- linux
|
||||
- sublime-text
|
||||
- ubuntu
|
||||
---
|
||||
After reading numerous blog posts about how to install [Sublime Text 2](http://www.sublimetext.com/2 "Sublime Text 2") in [Ubuntu](http://www.ubuntu.com/2 "Ubuntu"), this is definitely the quickest way!
|
||||
|
||||
After reading numerous blog posts about how to install
|
||||
[Sublime Text 2](http://www.sublimetext.com/2 'Sublime Text 2') in
|
||||
[Ubuntu](http://www.ubuntu.com/2 'Ubuntu'), this is definitely the quickest way!
|
||||
|
||||
Just paste the following lines into your Terminal:
|
||||
|
||||
|
@ -17,4 +22,6 @@ $ sudo apt-get update
|
|||
$ sudo apt-get install sublime-text
|
||||
```
|
||||
|
||||
After running this, Sublime Text 2 has been installed within the */usr/lib/sublime-text-2* directory and can be launched from the Dashboard, or by typing `subl`, `sublime-text` or `sublime-text-2` into a Terminal window.
|
||||
After running this, Sublime Text 2 has been installed within the
|
||||
_/usr/lib/sublime-text-2_ directory and can be launched from the Dashboard, or
|
||||
by typing `subl`, `sublime-text` or `sublime-text-2` into a Terminal window.
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
---
|
||||
title: Quickly Apply Patches Using Git and curl or wget
|
||||
date: 2013-12-24
|
||||
excerpt: How to quickly download a patch file and apply it to a Git repository in one line
|
||||
excerpt:
|
||||
How to quickly download a patch file and apply it to a Git repository in one
|
||||
line
|
||||
tags:
|
||||
- git
|
||||
- drupal-planet
|
||||
---
|
||||
Testing a patch file is usually a two-step process. First you download the patch file from the source, and then you run a separate command to apply it.
|
||||
|
||||
Testing a patch file is usually a two-step process. First you download the patch
|
||||
file from the source, and then you run a separate command to apply it.
|
||||
|
||||
You can save time and typing by running the two commands on one line:
|
||||
|
||||
|
@ -20,6 +24,8 @@ Or, if you don't have curl installed, you can use wget:
|
|||
$ wget -q -O - http://drupal.org/files/[patch-name].patch | git apply -v
|
||||
```
|
||||
|
||||
These commands need to be run within the root of your Git repository (i.e. where the .git directory is).
|
||||
These commands need to be run within the root of your Git repository (i.e. where
|
||||
the .git directory is).
|
||||
|
||||
These snippets were taken from [Applying Patches with Git](https://drupal.org/node/1399218) on Drupal.org.
|
||||
These snippets were taken from
|
||||
[Applying Patches with Git](https://drupal.org/node/1399218) on Drupal.org.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue