diff --git a/sculpin/.envrc b/sculpin/.envrc new file mode 100644 index 000000000..3550a30f2 --- /dev/null +++ b/sculpin/.envrc @@ -0,0 +1 @@ +use flake diff --git a/sculpin/.gitignore b/sculpin/.gitignore new file mode 100644 index 000000000..034f9371b --- /dev/null +++ b/sculpin/.gitignore @@ -0,0 +1,21 @@ +/.phpunit.cache +/.phpunit.result.cache +/output_*/ +/vendor/ + +# Front-end assets. +node_modules +source/build + +# ATDC pages +/source/atdc/* + +# Direnv +/.direnv/ + +# Devenv +.devenv* +devenv.local.nix + +# Pre-commit +.pre-commit-config.yaml diff --git a/sculpin/.gitmodules b/sculpin/.gitmodules new file mode 100644 index 000000000..d72f66453 --- /dev/null +++ b/sculpin/.gitmodules @@ -0,0 +1,3 @@ +[submodule "source/atdc"] + path = source/atdc + url = forgejo@ssh.oliverdavies.uk:opdavies/atdc-pages.git diff --git a/sculpin/.ignore b/sculpin/.ignore new file mode 100644 index 000000000..682d0c8e4 --- /dev/null +++ b/sculpin/.ignore @@ -0,0 +1 @@ +*.mp3 diff --git a/sculpin/.mailmap b/sculpin/.mailmap new file mode 100644 index 000000000..f5b109164 --- /dev/null +++ b/sculpin/.mailmap @@ -0,0 +1,8 @@ +Oliver Davies <339813+opdavies@users.noreply.github.com> +Oliver Davies +Oliver Davies +Oliver Davies +Oliver Davies +Oliver Davies +Oliver Davies +Oliver Davies diff --git a/sculpin/.markdownlint.yaml b/sculpin/.markdownlint.yaml new file mode 100644 index 000000000..ff7d7cc82 --- /dev/null +++ b/sculpin/.markdownlint.yaml @@ -0,0 +1 @@ +MD013: false diff --git a/sculpin/.tmux-sessionizer b/sculpin/.tmux-sessionizer new file mode 100755 index 000000000..4e01b949d --- /dev/null +++ b/sculpin/.tmux-sessionizer @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +PATH="${PATH}:./vendor/bin" + +tmux new-window -dn scratch +tmux new-window -dn sculpin +tmux new-window -dn tailwind + +tmux send-keys -t sculpin "sculpin generate --server --watch" Enter +tmux send-keys -t tailwind "cd assets && tailwindcss --input css/tailwind.css --output ../source/build/tailwind.css --watch" Enter + +nvim . diff --git a/sculpin/.yamlfmt.yaml b/sculpin/.yamlfmt.yaml new file mode 100644 index 000000000..59940850b --- /dev/null +++ b/sculpin/.yamlfmt.yaml @@ -0,0 +1,5 @@ +--- +formatter: + include_document_start: true + retain_line_breaks_single: true + type: basic diff --git a/sculpin/README.md b/sculpin/README.md new file mode 100644 index 000000000..6b0f24ac1 --- /dev/null +++ b/sculpin/README.md @@ -0,0 +1,27 @@ +# oliverdavies.uk + +[My personal website][website], built with [Sculpin][] - a PHP-based static site generator. + +It contains pages about my products, services, public speaking and training, as well as my daily email archive, podcast episodes and old blog posts from earlier versions of the website. + +## Styling + +The styling is done using [Tailwind CSS]. + +## BrowserSync + +I have [BrowserSync][] installed and use it to watch for changes to files and [automatically refresh my browser][0] instead of using Sculpin's built-in development server. + +## Hosting + +The website is hosted on a 1GB DigitalOcean droplet alongside other static websites. + +I'm using Apache as my web server so I can easily manage redirects using the `.htaccess` file within the `source` directory.. + +As it's a static website, no PHP or database are needed. + +[0]: https://www.oliverdavies.uk/blog/sculpin-browsersync +[browsersync]: https://browsersync.io +[sculpin]: https://sculpin.io +[tailwind css]: https://tailwindcss.com +[website]: https://www.oliverdavies.uk diff --git a/sculpin/app/SculpinKernel.php b/sculpin/app/SculpinKernel.php new file mode 100644 index 000000000..a88406150 --- /dev/null +++ b/sculpin/app/SculpinKernel.php @@ -0,0 +1,14 @@ +Book a Drupal 7 upgrade consultation call or an upgrade roadmap. + d7eol: | + Are you stuck on Drupal 7? Plan your upgrade to Drupal 10 now! + module: | + If you're creating a new Drupal module, try my free Drupal module template. + sponsor: | + Do you want to contribute more to open source but don't have the time? Sponsor me to do it for you! + subscription: | + Do you need immediate access to an expert Drupal Developer? With my Drupal development subscription, make unlimited requests for a fixed monthly price in less time than posting to a job board! + testing_course: | + Do you want to learn about automated testing in Drupal? Take my free 10-day email course and get daily lessons straight to your inbox. + pair: | + Need help or want another pair of eyes on your code? Book a 1-on-1 consulting call or an online pair programming session with a 100% money-back guarantee., + +drupalorg: + url: https://www.drupal.org/u/%drupalorg.username% + username: opdavies + +features: + new_css: false + show_blog_post_count: true + +github: + url: https://github.com/%github.username% + username: opdavies + +mastodon: + username: opdavies + url: https://mastodon.social/@%mastodon.username% + +menu_links: + - title: Home + url: / + - title: Presentations + url: /presentations + - title: Blog + url: /blog + - title: Podcast + url: /podcast + attributes: + title: The Beyond Blocks Podcast + - title: Books + url: /books + - title: Sponsor me + url: /sponsor + - title: Contact + url: 'mailto:%email%' + attributes: + title: Contact Oliver + +meta: + description: |- + Oliver is an Acquia-certified Triple Drupal expert, core contributor, Developer, Consultant and multiple-time DrupalCon speaker. + +testimonials: + - text: | + Oliver devised a creative and original approach to Drupal theme switching based on Tailwind and provided us with the building blocks and basic theming. + + He gave several helpful mentoring sessions with our front end developer to support us to build this approach into our site. + name: Technical Director, European knowledge platform + image: ~ + tags: [front] + - text: | + This course is really great and I've recommended it to my coworkers here at Palantir.net. + name: Daniel Davis-Boxleitner + title: Senior Engineer at Palantir.net + image: + url: /assets/images/recommendations/daniel-davis-boxleitner.jpg + tags: [testing, atdc] + - text: | + The course was very informative. One of the biggest pain points with Drupal testing was that there was no clear and definitive guide on setting up the php unit XML file to get functional and kernel tests working right away. Your guide was fantastic and I will definitely be using it going forward in my module development for work. + name: Frank Landry + title: ~ + image: + url: /assets/images/recommendations/frank-landry.jpg + tags: [testing, atdc] + - text: | + Well done. You've created a really excellent resource here that has the potential to bring Drupal development forward a huge leap. You’ve managed to simplify and share some often complex seeming issues. + name: Adam Nuttall + title: Drupal Engineer + image: + url: /assets/images/recommendations/adam-nuttall.jpg + tags: [testing, atdc] + - text: | + I'm liking your short emails. They're just the right length that isn't too distracting but I'm able to consume it in a single glance. + name: Kevin Coyle + title: Design System Engineering Consultant + url: https://www.coyledesign.co.uk + image: + url: /assets/images/recommendations/kevin-coyle.jpg + tags: [daily] + - text: | + I really love your daily posts. They are opinionated, and this gives room for thoughts, I appreciate this. + name: Boris Böhne + title: Drupal Developer + url: https://www.drupal.org/u/drubb + image: + url: /assets/images/recommendations/boris-bohne.jpg + tags: [daily] + - text: | + Following your "Automated tests" emails and they are great! Such a pleasant reading. I love how you start from the very beginning and keeping things simple, step by step. + + Looking forward to more content! + name: Matthieu Scarset + title: Drupal Expert + url: https://matthieuscarset.com + image: + url: /assets/images/recommendations/matthieu-scarset.jpg + tags: [testing, atdc] + - text: | + Hi Oliver, we met briefly at the Tech Connect event in London last month. Been reading through a few of your latest posts and have found the messages valuable, especially as we spent the week learning about unit, integration and e2e testing. I have signed up to your mailing list to keep the good advice flowing! + name: Alexander Carr + title: Full Stack Software Engineer at School of Code + image: + url: /assets/images/recommendations/alexander-carr.jpg + tags: [daily] + - text: | + These emails are superb and make for very interesting reading. Thank you! + name: Adam Nuttall + title: Drupal Engineer + image: + url: /assets/images/recommendations/adam-nuttall.jpg + tags: [daily] + - text: Oliver's approach to testing is a continual reminder of his commitment to delivering high-quality, bug-free, software. + name: Mike Karthauser + title: Senior Software Engineer + image: + url: /assets/images/recommendations/mike-karthauser.jpg + tags: [daily, testing, coaching, atdc] + - text: | + I had the opportunity and good fortune to work with Oliver solving two problems that I was having on a Drupal Commerce site. I have done several Drupal sites using UberCart, but since it is deprecated, I chose to use Commerce. I had searched, posted to forums, and other normal means to find answers to my problems, to no response and to no avail. + + I got a referral to Oliver and scheduled an appointment to discuss the problems on a Zoom call. After showing him via screen share where I was stumped, he offered different approaches to what I was doing, which I was fine with as long as it worked. + + Once we solved the first problem, I was really elated and then focused on the second one, which was an easier fix. So in a short period of time, both problems were fixed and tested. + + I found Oliver was affable and easy to work with. He has a strong work ethic and a desire to solve problems for his customers and can recommend working with him. I think one of his strengths is to find alternative solutions to problems. + name: Tom Evans + title: ~ + image: ~ + tags: [call] + - text: | + I am a big fan of your git approaches. I especially remember pairing with you and watching how many commands you run to solve many problems and how fast you were. It's a skill I believe not many have, particularly those who are used to working with a GUI like me, and personally I think it is quite valuable. + name: Marcos Duran + title: Senior Software Engineer + image: + url: /assets/images/recommendations/marcos-duran.jpg + tags: [git, daily, coaching] + - text: | + I like the "$ git log -S" and "$ git log --grep" commands, will definitely be using these, thanks! + name: Stephen Mulvihill + title: Solutions Architect + image: + url: /assets/images/recommendations/stephen-mulvihill.jpg + tags: [git, daily, coaching] + - text: | + Just wanted to say that your blog is amazing <3 I absolutely love it and usually share it with colleagues and some of the kids at my Code Club. + + Thanks for contributing to the community with your amazing content! + name: Patty O'Callaghan + title: Tech Lead + url: https://pattyocallaghan.com + image: + url: /assets/images/recommendations/patty-ocallaghan.jpg + tags: [daily] + - text: | + I've wanted to explore testing for a while, but as a PHP developer with 10 years of Drupal experience who'd written next to no tests, I really needed guidance. Oliver's expertise in testing and TDD motivated me to seek his help. + + Before our call, I'd started writing tests for my modules but needed direction, understanding the code to a degree but needing help with approach. Oliver clarified both unit and integration testing, providing solutions for my challenges, and shared his code for inspiration and help. He also gave me ideas on how to utilise contrib code to help me further. + + Consulting with an expert, I gained the clarity and confidence I needed in tackling testing with structured, maintainable practices. Oliver's adaptability and tailored services make him highly recommendable. + + Thanks, Oliver - I feel empowered and know exactly what approach to take now! + name: Tawny Bartlett + title: Senior Drupal Developer + url: https://www.playingwithpixels.co.uk + image: + url: /assets/images/recommendations/tawny.jpg + tags: [testing, coaching, call, atdc] + - text: | + I've worked with Oliver for a number of years on B2C and B2B web projects and he has always demonstrated himself to be an expert in his field. + + As an insurance provider, some of our products and services don't naturally fit within a traditional ecommerce journey - but Oliver has always been able to come up with innovative ways to leverage core Drupal functionality and develop custom modules to meet our needs. + + Friendly, flexible and diligent - I wouldn't hesitate to recommend Oliver to anyone looking for a Drupal developer to progress their next project. + name: Joe Howell + title: Director, Bastion Insurance + url: https://www.bastioninsurance.co.uk + image: + url: /assets/images/recommendations/joe-howell.jpg + tags: [front, subscription, coaching] + - text: | + We use Oliver for maintaining a couple of Drupal sites for which we no longer have the skills ourselves. We became aware of Oliver through his work in the Drupal community, and about a year ago we approached him to help us with the deep dive aspects of maintaining and developing Drupal sites. He's been really helpful and very responsive. Much appreciated! + name: Jon Hallett + title: Senior Systems Administrator at the University of Bristol + url: https://bristol.ac.uk + image: + url: /assets/images/recommendations/jon-hallett.jpeg + tags: [front, subscription] + - text: | + For over a decade we have worked with Oliver on a number of different projects. Initially our collaboration consisted of web maintenance and troubleshooting but we soon tapped Oliver to design, build and maintain a custom awards site which includes both submission and judging functionality. Oliver has deep and wide-ranging skills and I would certainly recommend his services! + name: Michael Itkoff + title: Cofounder + url: https://www.daylightbooks.org + image: + url: /assets/images/recommendations/michael-itkoff.jpg + tags: [front, subscription] + - text: | + Working with Oliver on the Seren website has been easy and beneficial. + + As well as providing general maintenance support, he built a new Drupal module which integrated with our partners Glassboxx so that we could sell ebooks directly from our website. Oliver worked closely with the team at Glassboxx to create the integration which needed to communicate with the Glassboxx app so that users could download their purchases. He was able to resolve issues which came up along the way in order to create a functioning module which we now use on our site. + + Oliver has extensive knowledge of Drupal and his familiarity with the Seren site meant he was able to fix problems quickly and efficiently as they arose. + + He is reliable and has always been willing to discuss new ideas for how the site could function. + + We would recommend working with him for his invaluable knowledge and ability to find solutions to problems at short notice. It has been a pleasure to work with him over the years. + name: Mick Felton + title: Publisher at Poetry Wales Press Ltd (Seren Books) + url: https://www.serenbooks.com + image: + url: /assets/images/recommendations/mick-felton.jpg + tags: [front, subscription, coaching] + - text: | + Oliver is a pleasure to work with, and I would engage him again without hesitation. He communicates regularly, ensures that he meets requirements, and suggests improvements to the potential solutions to the brief. + name: Duncan Davidson + title: Director at Rohallion + url: https://rohallion.agency + image: + url: /assets/images/recommendations/duncan.jpeg + tags: [front, subscription, coaching] + - text: | + We have only worked together for a short while but I can see Oliver is a Drupal expert. + + His technical knowledge means we have been able to make improvements to the sites we manage quickly and efficiently. + + If we have complex issues to contend with in the future I feel confident he will be able to deal with them. + name: Anonymous + title: Marketing Strategist + tags: [front, subscription] + - text: | + A fantastic and highly knowledgeable Drupal Developer. Oliver saved a struggling Drupal project with his wealth of Drupal experience. + name: Adam Cuddihy + title: Web Development Manager + url: ~ + image: + url: /assets/images/recommendations/adam.jpeg + tags: [front, subscription] + - text: | + I had the pleasure of working with Oliver whilst building the first version of our drupal based intranet. His knowledge of Drupal and the wider infrastructure required to run a site was really invaluable. + + At the time, we were very new to Drupal, so it gave us a great platform to learn from and expand our own knowledge. + + He's the only external contractor that we've kept in touch with over the years, which goes to show how much we valued his input. + name: Huw Davies + title: Web Dev Manager / DevOps / Team Manager at Admiral Group Plc + url: https://admiral.com + image: + url: /assets/images/recommendations/huw.jpeg + tags: [front, subscription] + - text: | + Oliver really knows his stuff. Whether you are just starting out or looking to take your knowledge to the next level, his patient and clear way of explaining will help get you there. + name: Scott Euser + title: Head of Web Development + url: ~ + image: + url: /assets/images/recommendations/scott-euser.jpg + tags: [testing, coaching] + - text: | + I have had the pleasure of working with Oliver on several projects at Microserve. He is a natural innovator and a great mentor who inspires others to explore new technologies and approaches. He is a highly knowledgeable professional with a passion for all things Drupal and the tenacity required to get the job done well. + name: Alan Hatch + title: Senior Drupal Developer at Microserve + url: ~ + image: + url: /assets/images/recommendations/alan.jpeg + tags: [coaching] + - text: | + Oliver has been an outstanding contributor to the Drupal Association team. He is a talented developer who writes great code and applies his curiosity and love of learning to every project. He is also a fantastic team member, who gives to the team as much as he gets. + + Oliver is the embodiment of everything good about the Drupal community. + name: Holly Ross + title: Executive Director at the Drupal Association + url: https://www.drupal.org/association + image: + url: /assets/images/recommendations/holly-ross.png + tags: [front, subscription] + - text: | + Oliver is a skilled Drupal developer with a passion for the Drupal community. As his direct supervisor, I was able to watch Oliver grow with the Drupal Association and contribute an amazing amount of effort and integrity to all of his work. + + Everything we have thrown at Oliver, he has approached with an open and flexible mind that has allowed him to work on a wide range of projects and features for Drupal products. + name: Josh Mitchell + title: CTO at Drupal Association + url: https://joshuami.com + image: + url: /assets/images/recommendations/josh-mitchell.png + tags: [front, subscription] + - text: | + Oliver was great to work with. He has expert knowledge with Drupal and delivered exactly what we were looking for on time. He's understanding, friendly and easy to get along with. I would enjoy working with him again in the future. + name: Brian Hartwell + title: Interactive Creative Director + url: ~ + image: ~ + tags: [front, subscription] + - text: | + Oliver was fantastic to work with - pro-active and highly responsive, he worked well remotely and as part of a project team. His understanding of the project requirement(s) and ability to translate it into working code was essential and he delivered. + name: Brian Healy + title: Director of Business Development at Tincan + url: ~ + image: + url: /assets/images/recommendations/brian-healy.png + tags: [front, subscription] + - text: | + Oliver is an amazing colleague, he's professional, full of knowledge and I could not recommend him more. + name: Chris Jarvis + title: Developer at Microserve + url: ~ + image: + url: /assets/images/recommendations/chris-jarvis.jpg + - text: | + Oliver is seasoned Drupal and all round highly skilled and experienced web developer. I have worked with Oliver on an important project where he was reliable, prompt and ensured strict client deadline delivery and confidentiality at all times. + name: Daniel Easterbrook + title: Digital Strategy Consultant + tags: [front, subscription] + +prose_classes: | + prose prose-p:text-black prose-a:font-light prose-a:text-blue-primary prose-p:text-lg prose-blockquote:border-blue-primary dark:marker:text-white prose-li:my-1 prose-li:text-lg prose-figcaption:text-white prose-li:text-black marker:text-black dark:prose-p:text-white dark:prose-invert dark:prose-a:text-blue-400 dark:prose-blockquote:border-blue-400 dark:prose-li:text-white hover:prose-a:no-underline prose-h2:text-xl prose-code:font-normal prose-h2:mb-4 prose-ul:my-3 dark:prose-hr:border-grey-400 prose-code:before:content-[''] prose-code:after:content-[''] + +transistor: + feed: + url: https://feeds.transistor.fm/beyond-blocks + share: + url: https://share.transistor.fm/e + +youtube: + channel: + slug: opdavies + url: https://www.youtube.com/@%youtube.channel.slug% diff --git a/sculpin/app/config/sculpin_site_prod.yml b/sculpin/app/config/sculpin_site_prod.yml new file mode 100644 index 000000000..2dc91cafa --- /dev/null +++ b/sculpin/app/config/sculpin_site_prod.yml @@ -0,0 +1,8 @@ +--- +imports: + - sculpin_site.yml + +features: + new_css: false + +url: https://www.oliverdavies.uk diff --git a/sculpin/assets/css/tailwind.css b/sculpin/assets/css/tailwind.css new file mode 100644 index 000000000..6e6c50fef --- /dev/null +++ b/sculpin/assets/css/tailwind.css @@ -0,0 +1,11 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + @font-face { + font-family: Roboto Condensed; + font-weight: 300 400 500 700; + src: url('../assets/fonts/RobotoCondensed-VariableFont_wght.ttf') format('truetype'); + } +} diff --git a/sculpin/assets/tailwind.config.ts b/sculpin/assets/tailwind.config.ts new file mode 100644 index 000000000..0b17b0d79 --- /dev/null +++ b/sculpin/assets/tailwind.config.ts @@ -0,0 +1,38 @@ +import colours from "tailwindcss/colors"; +import type { Config } from "tailwindcss"; +import formsPlugin from '@tailwindcss/forms'; +import typographyPlugin from "@tailwindcss/typography"; + +export default { + content: [ + "../app/config/**/*.yml", + "../source/**/*.{md,twig}", + ], + theme: { + colors: { + black: "#000", + blue: { + primary: "#24608A", + 400: "#60a5fa", + }, + current: "currentColor", + grey: colours.stone, + inherit: "inherit", + transparent: "transparent", + white: "#fff", + }, + + extend: { + fontFamily: { + sans: [ + "Roboto Condensed", + "Arial", + "Helvetica Neue", + "Helvetica", + "sans-serif", + ], + }, + }, + }, + plugins: [formsPlugin, typographyPlugin], +} satisfies Config; diff --git a/sculpin/build b/sculpin/build new file mode 100755 index 000000000..2163f52ee --- /dev/null +++ b/sculpin/build @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -uexo pipefail + +vendor/bin/sculpin generate --watch --server "$@" diff --git a/sculpin/composer.json b/sculpin/composer.json new file mode 100644 index 000000000..0cc6b3a51 --- /dev/null +++ b/sculpin/composer.json @@ -0,0 +1,28 @@ +{ + "require": { + "opdavies/sculpin-twig-markdown-bundle": "^0.2.0", + "sculpin/sculpin": "^3.2" + }, + "config": { + "allow-plugins": { + "sculpin/sculpin-theme-composer-plugin": true, + "phpstan/extension-installer": true + } + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "require-dev": { + "phpunit/phpunit": "^12.1", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/extension-installer": "^1.4" + } +} diff --git a/sculpin/composer.lock b/sculpin/composer.lock new file mode 100644 index 000000000..c4b484ca1 --- /dev/null +++ b/sculpin/composer.lock @@ -0,0 +1,5312 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "c0c52dda2be448215af08587bbcd86c5", + "packages": [ + { + "name": "dflydev/ant-path-matcher", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-util-antPathMatcher.git", + "reference": "c8406d2d85a844b0dbb4ee76d9db9def7ca67518" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-util-antPathMatcher/zipball/c8406d2d85a844b0dbb4ee76d9db9def7ca67518", + "reference": "c8406d2d85a844b0dbb4ee76d9db9def7ca67518", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^4|^5|^6|^7|^8|^9" + }, + "type": "library", + "autoload": { + "psr-0": { + "dflydev\\util\\antPathMatcher": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Ant Path Matcher Utility", + "homepage": "http://github.com/dflydev/dflydev-util-antPathMatcher", + "keywords": [ + "ant", + "matcher", + "path", + "pattern" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-util-antPathMatcher/issues", + "source": "https://github.com/dflydev/dflydev-util-antPathMatcher/tree/v1.0.4" + }, + "time": "2023-01-23T23:02:42+00:00" + }, + { + "name": "dflydev/apache-mime-types", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-apache-mime-types.git", + "reference": "f30a57e59b7476e4c5270b6a0727d79c9c0eb861" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-apache-mime-types/zipball/f30a57e59b7476e4c5270b6a0727d79c9c0eb861", + "reference": "f30a57e59b7476e4c5270b6a0727d79c9c0eb861", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "twig/twig": "1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\ApacheMimeTypes": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Apache MIME Types", + "keywords": [ + "apache", + "mime", + "mimetypes" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-apache-mime-types/issues", + "source": "https://github.com/dflydev/dflydev-apache-mime-types/tree/v1.0.1" + }, + "time": "2013-05-14T02:02:01+00:00" + }, + { + "name": "dflydev/canal", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-canal.git", + "reference": "668af213d86f0f378f5dcce6799b974044fa6a51" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-canal/zipball/668af213d86f0f378f5dcce6799b974044fa6a51", + "reference": "668af213d86f0f378f5dcce6799b974044fa6a51", + "shasum": "" + }, + "require": { + "dflydev/apache-mime-types": "1.0.*", + "php": ">=5.3.3", + "webignition/internet-media-type": "0.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\Canal": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Content analysis for the purpose of determining Internet media types.", + "keywords": [ + "content", + "detection", + "mime", + "type" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-canal/issues", + "source": "https://github.com/dflydev/dflydev-canal/tree/master" + }, + "time": "2013-05-14T05:22:25+00:00" + }, + { + "name": "dflydev/dot-access-configuration", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-configuration.git", + "reference": "2e6eb0c8b8830b26bb23defcfc38d4276508fc49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-configuration/zipball/2e6eb0c8b8830b26bb23defcfc38d4276508fc49", + "reference": "2e6eb0c8b8830b26bb23defcfc38d4276508fc49", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "1.*", + "dflydev/placeholder-resolver": "1.*", + "php": ">=5.3.2" + }, + "require-dev": { + "symfony/yaml": "~2.1" + }, + "suggest": { + "symfony/yaml": "Required for using the YAML Configuration Builders" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\DotAccessConfiguration": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Given a deep data structure representing a configuration, access configuration by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-configuration", + "keywords": [ + "config", + "configuration" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-configuration/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-configuration/tree/master" + }, + "time": "2018-09-08T23:00:17+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/3fbd874921ab2c041e899d044585a2ab9795df8a", + "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\DotAccessData": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/master" + }, + "time": "2017-01-20T21:14:22+00:00" + }, + { + "name": "dflydev/placeholder-resolver", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-placeholder-resolver.git", + "reference": "d0161b4be1e15838327b01b21d0149f382d69906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-placeholder-resolver/zipball/d0161b4be1e15838327b01b21d0149f382d69906", + "reference": "d0161b4be1e15838327b01b21d0149f382d69906", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\PlaceholderResolver": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Given a data source representing key => value pairs, resolve placeholders like ${foo.bar} to the value associated with the 'foo.bar' key in the data source.", + "homepage": "https://github.com/dflydev/dflydev-placeholder-resolver", + "keywords": [ + "placeholder", + "resolver" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-placeholder-resolver/issues", + "source": "https://github.com/dflydev/dflydev-placeholder-resolver/tree/v1.0.3" + }, + "time": "2021-12-03T16:48:58+00:00" + }, + { + "name": "doctrine/inflector", + "version": "1.4.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", + "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector", + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/1.4.4" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2021-04-16T17:34:40+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fig/http-message-util", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message-util.git", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message-util/zipball/9d94dc0154230ac39e5bf89398b324a86f63f765", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "suggest": { + "psr/http-message": "The package containing the PSR-7 interfaces" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fig\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-message-util/issues", + "source": "https://github.com/php-fig/http-message-util/tree/1.1.5" + }, + "time": "2020-11-24T22:02:12+00:00" + }, + { + "name": "michelf/php-markdown", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/michelf/php-markdown.git", + "reference": "5024d623c1a057dcd2d076d25b7d270a1d0d55f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/5024d623c1a057dcd2d076d25b7d270a1d0d55f3", + "reference": "5024d623c1a057dcd2d076d25b7d270a1d0d55f3", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.3 <5.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Michelf\\": "Michelf/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "https://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "https://daringfireball.net/" + } + ], + "description": "PHP Markdown", + "homepage": "https://michelf.ca/projects/php-markdown/", + "keywords": [ + "markdown" + ], + "support": { + "issues": "https://github.com/michelf/php-markdown/issues", + "source": "https://github.com/michelf/php-markdown/tree/1.9.1" + }, + "time": "2021-11-24T02:52:38+00:00" + }, + { + "name": "netcarver/textile", + "version": "v3.8.0", + "source": { + "type": "git", + "url": "https://github.com/textile/php-textile.git", + "reference": "02ed0cbe6832c2100342dabb6d01d7ba558cb8e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/textile/php-textile/zipball/02ed0cbe6832c2100342dabb6d01d7ba558cb8e7", + "reference": "02ed0cbe6832c2100342dabb6d01d7ba558cb8e7", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpstan/phpstan": "1.6.3", + "phpunit/phpunit": "^9.5.20", + "psy/psysh": "^0.11.2", + "squizlabs/php_codesniffer": "3.*", + "symfony/yaml": "^4.4.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.8-dev" + } + }, + "autoload": { + "psr-4": { + "Netcarver\\Textile\\": "src/Netcarver/Textile/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Textile markup language parser", + "homepage": "https://github.com/textile/php-textile", + "keywords": [ + "document", + "format", + "html", + "language", + "markup", + "parser", + "php-textile", + "plaintext", + "textile" + ], + "support": { + "issues": "https://github.com/textile/php-textile/issues", + "source": "https://github.com/textile/php-textile", + "wiki": "https://github.com/textile/php-textile/wiki" + }, + "time": "2022-12-03T18:19:42+00:00" + }, + { + "name": "opdavies/sculpin-twig-markdown-bundle", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://github.com/opdavies/sculpin-twig-markdown-bundle.git", + "reference": "da9b055a1981419a0e7d5b5e8e1de517d1d9d91e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opdavies/sculpin-twig-markdown-bundle/zipball/da9b055a1981419a0e7d5b5e8e1de517d1d9d91e", + "reference": "da9b055a1981419a0e7d5b5e8e1de517d1d9d91e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "sculpin/sculpin": "@stable" + }, + "type": "library", + "autoload": { + "psr-4": { + "Opdavies\\Sculpin\\Bundle\\TwigMarkdownBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Davies", + "email": "oliver@oliverdavies.uk", + "homepage": "https://www.oliverdavies.uk" + } + ], + "keywords": [ + "markdown", + "sculpin", + "twig" + ], + "support": { + "issues": "https://github.com/opdavies/sculpin-twig-markdown-bundle/issues", + "source": "https://github.com/opdavies/sculpin-twig-markdown-bundle/tree/master" + }, + "time": "2019-11-11T15:04:02+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/http-message", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/1.1" + }, + "time": "2023-04-04T09:50:52+00:00" + }, + { + "name": "psr/log", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/2.0.0" + }, + "time": "2021-07-14T16:41:46+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/dns", + "version": "v1.13.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.13.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-13T14:18:03+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+00:00" + }, + { + "name": "react/http", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/http.git", + "reference": "8db02de41dcca82037367f67a2d4be365b1c4db9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/http/zipball/8db02de41dcca82037367f67a2d4be365b1c4db9", + "reference": "8db02de41dcca82037367f67a2d4be365b1c4db9", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "fig/http-message-util": "^1.1", + "php": ">=5.3.0", + "psr/http-message": "^1.0", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.3 || ^1.2.1", + "react/socket": "^1.16", + "react/stream": "^1.4" + }, + "require-dev": { + "clue/http-proxy-react": "^1.8", + "clue/reactphp-ssh-proxy": "^1.4", + "clue/socks-react": "^1.4", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.2 || ^3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Http\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven, streaming HTTP client and server implementation for ReactPHP", + "keywords": [ + "async", + "client", + "event-driven", + "http", + "http client", + "http server", + "https", + "psr-7", + "reactphp", + "server", + "streaming" + ], + "support": { + "issues": "https://github.com/reactphp/http/issues", + "source": "https://github.com/reactphp/http/tree/v1.11.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-11-20T15:24:08+00:00" + }, + { + "name": "react/promise", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-05-24T10:39:05+00:00" + }, + { + "name": "react/socket", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.16.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-07-26T10:38:09+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sculpin/sculpin", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sculpin/sculpin.git", + "reference": "5f705d845b2dc980ed91b79c49ccaa5f64cbdda0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sculpin/sculpin/zipball/5f705d845b2dc980ed91b79c49ccaa5f64cbdda0", + "reference": "5f705d845b2dc980ed91b79c49ccaa5f64cbdda0", + "shasum": "" + }, + "require": { + "dflydev/ant-path-matcher": "^1.0.3", + "dflydev/apache-mime-types": "^1.0.1", + "dflydev/canal": "^1.0", + "dflydev/dot-access-configuration": "^1.0.3", + "doctrine/inflector": "^1.3", + "ext-mbstring": "*", + "michelf/php-markdown": "^1.9", + "netcarver/textile": "^3.6", + "php": "^8.0 || ^7.3", + "react/http": "^1.0", + "sculpin/sculpin-theme-composer-plugin": "^1.0", + "symfony/config": "^4.4.13", + "symfony/console": "^4.4.13", + "symfony/dependency-injection": "^4.4.13", + "symfony/event-dispatcher": "^4.4.13", + "symfony/filesystem": "^4.4.13", + "symfony/finder": "^4.4.13", + "symfony/http-kernel": "^4.4.13", + "symfony/yaml": "^4.4.13", + "twig/twig": "^2.5", + "webignition/internet-media-type": "^0.4.8" + }, + "replace": { + "sculpin/core": "self.version", + "sculpin/markdown-bundle": "self.version", + "sculpin/markdown-twig-compat-bundle": "self.version", + "sculpin/posts-bundle": "self.version", + "sculpin/proxy-source-collection-contrib": "self.version", + "sculpin/sculpin-bundle": "self.version", + "sculpin/standalone-bundle": "self.version", + "sculpin/taxonomy-contrib": "self.version", + "sculpin/textile-bundle": "self.version", + "sculpin/twig-bundle": "self.version" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpstan": "^1.2", + "phpunit/phpunit": "^9.4", + "squizlabs/php_codesniffer": "^3.3", + "symfony/css-selector": "^4.1", + "symfony/dom-crawler": "^4.1", + "symfony/process": "^4.1" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/sculpin", + "bin/sculpin.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sculpin\\": "src/Sculpin/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Static Site Generator", + "homepage": "https://sculpin.io", + "keywords": [ + "generator", + "site", + "static" + ], + "support": { + "issues": "https://github.com/sculpin/sculpin/issues", + "source": "https://github.com/sculpin/sculpin/tree/3.2.0" + }, + "time": "2022-10-31T19:34:13+00:00" + }, + { + "name": "sculpin/sculpin-theme-composer-plugin", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sculpin/sculpin-theme-composer-plugin.git", + "reference": "e3f4e1d6a10368709d07933f8391ef7e534c5db4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sculpin/sculpin-theme-composer-plugin/zipball/e3f4e1d6a10368709d07933f8391ef7e534c5db4", + "reference": "e3f4e1d6a10368709d07933f8391ef7e534c5db4", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1|^2.0" + }, + "require-dev": { + "composer/composer": "*" + }, + "type": "composer-plugin", + "extra": { + "class": "Sculpin\\Composer\\SculpinThemePlugin\\SculpinThemePlugin", + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Sculpin\\Composer\\SculpinThemePlugin\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Plugin for theming sculpin sites", + "support": { + "issues": "https://github.com/sculpin/sculpin-theme-composer-plugin/issues", + "source": "https://github.com/sculpin/sculpin-theme-composer-plugin/tree/1.0.3" + }, + "time": "2020-10-29T13:20:43+00:00" + }, + { + "name": "symfony/config", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "ed42f8f9da528d2c6cae36fe1f380b0c1d8f0658" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/ed42f8f9da528d2c6cae36fe1f380b0c1d8f0658", + "reference": "ed42f8f9da528d2c6cae36fe1f380b0c1d8f0658", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/filesystem": "^3.4|^4.0|^5.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22" + }, + "conflict": { + "symfony/finder": "<3.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^3.4|^4.0|^5.0", + "symfony/finder": "^3.4|^4.0|^5.0", + "symfony/messenger": "^4.1|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-20T09:59:04+00:00" + }, + { + "name": "symfony/console", + "version": "v4.4.49", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", + "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v4.4.49" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-05T17:10:16+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "1a692492190773c5310bc7877cb590c04c2f05be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/1a692492190773c5310bc7877cb590c04c2f05be", + "reference": "1a692492190773c5310bc7877cb590c04c2f05be", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "^3.4|^4.0|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "abandoned": "symfony/error-handler", + "time": "2022-07-28T16:29:46+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v4.4.49", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9065fe97dbd38a897e95ea254eb5ddfe1310f734", + "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/container": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/config": "<4.3|>=5.0", + "symfony/finder": "<3.4", + "symfony/proxy-manager-bridge": "<3.4", + "symfony/yaml": "<4.4.26" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/config": "^4.3", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/yaml": "^4.4.26|^5.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v4.4.49" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-16T16:18:09+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "be731658121ef2d8be88f3a1ec938148a9237291" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/be731658121ef2d8be88f3a1ec938148a9237291", + "reference": "be731658121ef2d8be88f3a1ec938148a9237291", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "^1|^2|^3", + "symfony/debug": "^4.4.5", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-28T16:29:46+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "1e866e9e5c1b22168e0ce5f0b467f19bba61266a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1e866e9e5c1b22168e0ce5f0b467f19bba61266a", + "reference": "1e866e9e5c1b22168e0ce5f0b467f19bba61266a", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/event-dispatcher-contracts": "^1.1", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/error-handler": "~3.4|~4.4", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-20T09:59:04+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "761c8b8387cfe5f8026594a75fdf0a4e83ba6974" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/761c8b8387cfe5f8026594a75fdf0a4e83ba6974", + "reference": "761c8b8387cfe5f8026594a75fdf0a4e83ba6974", + "shasum": "" + }, + "require": { + "php": ">=7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.10.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-20T09:59:04+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v4.4.42", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "815412ee8971209bd4c1eecd5f4f481eacd44bf5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/815412ee8971209bd4c1eecd5f4f481eacd44bf5", + "reference": "815412ee8971209bd4c1eecd5f4f481eacd44bf5", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v4.4.42" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-20T08:49:14+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "66bd787edb5e42ff59d3523f623895af05043e4f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/66bd787edb5e42ff59d3523f623895af05043e4f", + "reference": "66bd787edb5e42ff59d3523f623895af05043e4f", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-29T07:35:46+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v2.5.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "48ef1d0a082885877b664332b9427662065a360c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/48ef1d0a082885877b664332b9427662065a360c", + "reference": "48ef1d0a082885877b664332b9427662065a360c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "suggest": { + "symfony/http-client-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-28T08:37:04+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "3f38b8af283b830e1363acd79e5bc3412d055341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3f38b8af283b830e1363acd79e5bc3412d055341", + "reference": "3f38b8af283b830e1363acd79e5bc3412d055341", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "predis/predis": "^1.0|^2.0", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v5.4.48" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-13T18:58:02+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v4.4.51", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "ad8ab192cb619ff7285c95d28c69b36d718416c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ad8ab192cb619ff7285c95d28c69b36d718416c7", + "reference": "ad8ab192cb619ff7285c95d28c69b36d718416c7", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "^1|^2", + "symfony/error-handler": "^4.4", + "symfony/event-dispatcher": "^4.4", + "symfony/http-client-contracts": "^1.1|^2", + "symfony/http-foundation": "^4.4.30|^5.3.7", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/browser-kit": "<4.3", + "symfony/config": "<3.4", + "symfony/console": ">=5", + "symfony/dependency-injection": "<4.3", + "symfony/translation": "<4.2", + "twig/twig": "<1.43|<2.13,>=2" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^4.3|^5.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/console": "^3.4|^4.0", + "symfony/css-selector": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^4.3|^5.0", + "symfony/dom-crawler": "^3.4|^4.0|^5.0", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/finder": "^3.4|^4.0|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/routing": "^3.4|^4.0|^5.0", + "symfony/stopwatch": "^3.4|^4.0|^5.0", + "symfony/templating": "^3.4|^4.0|^5.0", + "symfony/translation": "^4.2|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^1.43|^2.13|^3.0.4" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v4.4.51" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-11-10T13:31:29+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce", + "reference": "fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "metapackage", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:11:13+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/42f18f170aa86d612c3559cfb3bd11a375df32c8", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.4.48" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-08T15:21:10+00:00" + }, + { + "name": "symfony/yaml", + "version": "v4.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "aeccc4dc52a9e634f1d1eebeb21eacfdcff1053d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/aeccc4dc52a9e634f1d1eebeb21eacfdcff1053d", + "reference": "aeccc4dc52a9e634f1d1eebeb21eacfdcff1053d", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v4.4.45" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-08-02T15:47:23+00:00" + }, + { + "name": "twig/twig", + "version": "v2.16.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "19185947ec75d433a3ac650af32fc05649b95ee1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/19185947ec75d433a3ac650af32fc05649b95ee1", + "reference": "19185947ec75d433a3ac650af32fc05649b95ee1", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.8" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^5.4.9|^6.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.16-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v2.16.1" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2024-09-09T17:53:56+00:00" + }, + { + "name": "webignition/disallowed-character-terminated-string", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/webignition/disallowed-character-terminated-string.git", + "reference": "1c35b8bacbb2e76837c0aa8538dc2468a1f10e6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webignition/disallowed-character-terminated-string/zipball/1c35b8bacbb2e76837c0aa8538dc2468a1f10e6e", + "reference": "1c35b8bacbb2e76837c0aa8538dc2468a1f10e6e", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.3", + "phpunit/phpunit": "~8.0", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "webignition\\DisallowedCharacterTerminatedString\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jon Cram", + "email": "webignition@gmail.com" + } + ], + "description": "A string terminated by one or more disallowed characters", + "homepage": "https://github.com/webignition/disallowed-character-terminated-string", + "keywords": [ + "string", + "terminated" + ], + "support": { + "issues": "https://github.com/webignition/disallowed-character-terminated-string/issues", + "source": "https://github.com/webignition/disallowed-character-terminated-string/tree/master" + }, + "time": "2019-12-20T15:52:44+00:00" + }, + { + "name": "webignition/internet-media-type", + "version": "0.4.8", + "source": { + "type": "git", + "url": "https://github.com/webignition/internet-media-type.git", + "reference": "1a5bbe38033b00b23acd5e1dd10489bb07eed77c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webignition/internet-media-type/zipball/1a5bbe38033b00b23acd5e1dd10489bb07eed77c", + "reference": "1a5bbe38033b00b23acd5e1dd10489bb07eed77c", + "shasum": "" + }, + "require": { + "php": ">=5.6.0", + "webignition/quoted-string": ">=0.2.1,<1.0", + "webignition/string-parser": ">=0.2.3,<1.0" + }, + "require-dev": { + "phpunit/phpunit": "~5.0", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "webignition\\InternetMediaType\\": "src/", + "webignition\\Tests\\InternetMediaType\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jon Cram", + "email": "jon@webignition.net" + } + ], + "description": "PHP model of an http://en.wikipedia.org/wiki/Internet_media_type", + "homepage": "https://github.com/webignition/internet-media-type", + "keywords": [ + "content type", + "content-type", + "internet media type", + "media type", + "media-type" + ], + "support": { + "issues": "https://github.com/webignition/internet-media-type/issues", + "source": "https://github.com/webignition/internet-media-type/tree/master" + }, + "time": "2018-03-12T14:54:00+00:00" + }, + { + "name": "webignition/quoted-string", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/webignition/quoted-string.git", + "reference": "88b36b7be067796683ab3668e175322842dd5313" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webignition/quoted-string/zipball/88b36b7be067796683ab3668e175322842dd5313", + "reference": "88b36b7be067796683ab3668e175322842dd5313", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "webignition/string-parser": ">=0.2.3,<1" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "webignition\\QuotedString\\": "src/", + "webignition\\Tests\\QuotedString\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jon Cram", + "email": "jon@webignition.net" + } + ], + "description": "A parser for string values that are encapsulated in double quotes (ASCII 34)", + "homepage": "https://github.com/webignition/quoted-string", + "keywords": [ + "parser", + "quoted-string" + ], + "support": { + "issues": "https://github.com/webignition/quoted-string/issues", + "source": "https://github.com/webignition/quoted-string/tree/master" + }, + "time": "2017-05-11T11:41:31+00:00" + }, + { + "name": "webignition/string-parser", + "version": "0.2.3", + "source": { + "type": "git", + "url": "https://github.com/webignition/string-parser.git", + "reference": "8591e28c05bd250bcc67b8001f3588995b9ef74b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webignition/string-parser/zipball/8591e28c05bd250bcc67b8001f3588995b9ef74b", + "reference": "8591e28c05bd250bcc67b8001f3588995b9ef74b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "webignition/disallowed-character-terminated-string": ">=1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "webignition\\StringParser\\": "src/", + "webignition\\Tests\\StringParser\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jon Cram", + "email": "jon@webignition.net" + } + ], + "description": "Abstract state-based string parser", + "homepage": "https://github.com/webignition/string-parser", + "keywords": [ + "parser", + "string" + ], + "support": { + "issues": "https://github.com/webignition/string-parser/issues", + "source": "https://github.com/webignition/string-parser/tree/master" + }, + "time": "2017-05-11T10:04:12+00:00" + } + ], + "packages-dev": [ + { + "name": "myclabs/deep-copy", + "version": "1.13.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-04-29T12:36:36+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.4.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + }, + "time": "2024-12-30T11:07:19+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpstan/extension-installer", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" + }, + "time": "2024-09-04T20:21:43+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.14", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "8f2e03099cac24ff3b379864d171c5acbfc6b9a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8f2e03099cac24ff3b379864d171c5acbfc6b9a2", + "reference": "8f2e03099cac24ff3b379864d171c5acbfc6b9a2", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2025-05-02T15:32:28+00:00" + }, + { + "name": "phpstan/phpstan-strict-rules", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-strict-rules.git", + "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", + "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0.4" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Extra strict and opinionated rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.4" + }, + "time": "2025-03-18T11:42:40+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "12.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "448f2c504d86dbff3949dcd02c95aa85db2c7617" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/448f2c504d86dbff3949dcd02c95aa85db2c7617", + "reference": "448f2c504d86dbff3949dcd02c95aa85db2c7617", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.4.0", + "php": ">=8.3", + "phpunit/php-file-iterator": "^6.0", + "phpunit/php-text-template": "^5.0", + "sebastian/complexity": "^5.0", + "sebastian/environment": "^8.0", + "sebastian/lines-of-code": "^4.0", + "sebastian/version": "^6.0", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "12.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-05-04T05:25:05+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/961bc913d42fe24a257bfff826a5068079ac7782", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:37+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:58+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:59:16+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:59:38+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "12.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "5ee57ad690bda2c487594577600931a99053436c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5ee57ad690bda2c487594577600931a99053436c", + "reference": "5ee57ad690bda2c487594577600931a99053436c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.3", + "phpunit/php-code-coverage": "^12.1.2", + "phpunit/php-file-iterator": "^6.0.0", + "phpunit/php-invoker": "^6.0.0", + "phpunit/php-text-template": "^5.0.0", + "phpunit/php-timer": "^8.0.0", + "sebastian/cli-parser": "^4.0.0", + "sebastian/comparator": "^7.0.1", + "sebastian/diff": "^7.0.0", + "sebastian/environment": "^8.0.0", + "sebastian/exporter": "^7.0.0", + "sebastian/global-state": "^8.0.0", + "sebastian/object-enumerator": "^7.0.0", + "sebastian/type": "^6.0.2", + "sebastian/version": "^6.0.0", + "staabm/side-effects-detector": "^1.0.5" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "12.1-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.1.4" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-05-02T07:01:56+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/6d584c727d9114bcdc14c86711cd1cad51778e7c", + "reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:53:50+00:00" + }, + { + "name": "sebastian/comparator", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "b478f34614f934e0291598d0c08cbaba9644bee5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b478f34614f934e0291598d0c08cbaba9644bee5", + "reference": "b478f34614f934e0291598d0c08cbaba9644bee5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/diff": "^7.0", + "sebastian/exporter": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-07T07:00:32+00:00" + }, + { + "name": "sebastian/complexity", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0", + "symfony/process": "^7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:46+00:00" + }, + { + "name": "sebastian/environment", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8afe311eca49171bf95405cc0078be9a3821f9f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8afe311eca49171bf95405cc0078be9a3821f9f2", + "reference": "8afe311eca49171bf95405cc0078be9a3821f9f2", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:56:08+00:00" + }, + { + "name": "sebastian/exporter", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "76432aafc58d50691a00d86d0632f1217a47b688" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/76432aafc58d50691a00d86d0632f1217a47b688", + "reference": "76432aafc58d50691a00d86d0632f1217a47b688", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:56:42+00:00" + }, + { + "name": "sebastian/global-state", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/570a2aeb26d40f057af686d63c4e99b075fb6cbc", + "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:56:59+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:28+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:48+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:17+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/c405ae3a63e01b32eb71577f8ec1604e39858a7c", + "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T05:00:01+00:00" + }, + { + "name": "sebastian/type", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "1d7cd6e514384c36d7a390347f57c385d4be6069" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/1d7cd6e514384c36d7a390347f57c385d4be6069", + "reference": "1d7cd6e514384c36d7a390347f57c385d4be6069", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-18T13:37:31+00:00" + }, + { + "name": "sebastian/version", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T05:00:38+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/sculpin/flake-modules/dev-shell.nix b/sculpin/flake-modules/dev-shell.nix new file mode 100644 index 000000000..19b1cb76e --- /dev/null +++ b/sculpin/flake-modules/dev-shell.nix @@ -0,0 +1,29 @@ +{ inputs, ... }: + +{ + imports = [ inputs.devshell.flakeModule ]; + + perSystem = + { pkgs, self', ... }: + { + devshells.default = { + packages = with pkgs; [ + nodePackages.browser-sync + + (php83.buildEnv { + extraConfig = '' + error_reporting = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED + ''; + }) + + php83Packages.composer + + self'.packages.drafts + self'.packages.new-draft + self'.packages.publish + + tailwindcss + ]; + }; + }; +} diff --git a/sculpin/flake-modules/drafts.nix b/sculpin/flake-modules/drafts.nix new file mode 100644 index 000000000..f1ac84955 --- /dev/null +++ b/sculpin/flake-modules/drafts.nix @@ -0,0 +1,16 @@ +{ + perSystem = + { pkgs, ... }: + { + packages.drafts = pkgs.writeShellApplication { + name = "drafts"; + + runtimeInputs = with pkgs; [ gnugrep ]; + + text = '' + echo "oob" + grep -r 'draft: true' "''${1:-source}" + ''; + }; + }; +} diff --git a/sculpin/flake-modules/new-draft.nix b/sculpin/flake-modules/new-draft.nix new file mode 100644 index 000000000..31ee75800 --- /dev/null +++ b/sculpin/flake-modules/new-draft.nix @@ -0,0 +1,33 @@ +{ + perSystem = + { pkgs, ... }: + { + packages.new-draft = pkgs.writeShellApplication { + name = "new-draft"; + + runtimeInputs = with pkgs; [ + coreutils + git + ]; + + text = '' + title="$1" + + exclude_words="for|at|and" + + filtered_title=$(echo "$title" | sed -E "s/\b($exclude_words)\b//g") + + slug=$(echo "$filtered_title" | tr '[:upper:]' '[:lower:]' | sed -e 's/[^a-z0-9]/-/g' -e 's/-\+/-/g' -e 's/^-//g' -e 's/-$//g') + + file="source/_posts/$slug.md" + + echo -e "---\ntitle: $title\ndate: ~\ndraft: true\n---" > "$file" + + echo "File created: $file" + + git add "$file" + git commit -s -m "Add draft: $title" + ''; + }; + }; +} diff --git a/sculpin/flake-modules/publish.nix b/sculpin/flake-modules/publish.nix new file mode 100644 index 000000000..d15ee49aa --- /dev/null +++ b/sculpin/flake-modules/publish.nix @@ -0,0 +1,21 @@ +{ + perSystem = + { pkgs, ... }: + { + packages.publish = pkgs.writeShellApplication { + name = "publish"; + + runtimeInputs = with pkgs; [ + rsync + php + ]; + + text = '' + vendor/bin/sculpin generate --env prod + + rsync -uvrP static/ output_prod "$@" + rsync -uvrP output_prod/ nixedo.oliverdavies.uk:/var/www/vhosts/website-sculpin "$@" + ''; + }; + }; +} diff --git a/sculpin/flake-modules/systems.nix b/sculpin/flake-modules/systems.nix new file mode 100644 index 000000000..ce708c68b --- /dev/null +++ b/sculpin/flake-modules/systems.nix @@ -0,0 +1,3 @@ +{ + systems = [ "x86_64-linux" ]; +} diff --git a/sculpin/flake.lock b/sculpin/flake.lock new file mode 100644 index 000000000..b94f97353 --- /dev/null +++ b/sculpin/flake.lock @@ -0,0 +1,98 @@ +{ + "nodes": { + "devshell": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1741473158, + "narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=", + "owner": "numtide", + "repo": "devshell", + "rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1754487366, + "narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "import-tree": { + "locked": { + "lastModified": 1752730890, + "narHash": "sha256-GES8fapSLGz36MMPRVNkSUWXUTtqvGQNXHjRmRLfJUY=", + "owner": "vic", + "repo": "import-tree", + "rev": "6ebb8cb87987b20264c09296166543fd3761d274", + "type": "github" + }, + "original": { + "owner": "vic", + "repo": "import-tree", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1753579242, + "narHash": "sha256-zvaMGVn14/Zz8hnp4VWT9xVnhc8vuL3TStRqwk22biA=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "0f36c44e01a6129be94e3ade315a5883f0228a6e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "devshell": "devshell", + "flake-parts": "flake-parts", + "import-tree": "import-tree", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/sculpin/flake.nix b/sculpin/flake.nix new file mode 100644 index 000000000..bd0de9bc3 --- /dev/null +++ b/sculpin/flake.nix @@ -0,0 +1,20 @@ +{ + inputs = { + devshell.inputs.nixpkgs.follows = "nixpkgs"; + devshell.url = "github:numtide/devshell"; + + flake-parts.url = "github:hercules-ci/flake-parts"; + + import-tree.url = "github:vic/import-tree"; + + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = + inputs: + inputs.flake-parts.lib.mkFlake { inherit inputs; } { + imports = [ + (inputs.import-tree ./flake-modules) + ]; + }; +} diff --git a/sculpin/phpstan-baseline.neon b/sculpin/phpstan-baseline.neon new file mode 100644 index 000000000..3a319e890 --- /dev/null +++ b/sculpin/phpstan-baseline.neon @@ -0,0 +1,19 @@ +parameters: + ignoreErrors: + - + message: '#^Dynamic call to static method PHPUnit\\Framework\\Assert\:\:identicalTo\(\)\.$#' + identifier: staticMethod.dynamicCall + count: 1 + path: tests/Presentation/TwigExtension/PresentationTwigExtensionTest.php + + - + message: '#^Static method PHPUnit\\Framework\\Assert\:\:assertSame\(\) invoked with named argument \$actual, but it''s not allowed because of @no\-named\-arguments\.$#' + identifier: argument.named + count: 1 + path: tests/Presentation/TwigExtension/PresentationTwigExtensionTest.php + + - + message: '#^Static method PHPUnit\\Framework\\Assert\:\:assertSame\(\) invoked with named argument \$expected, but it''s not allowed because of @no\-named\-arguments\.$#' + identifier: argument.named + count: 1 + path: tests/Presentation/TwigExtension/PresentationTwigExtensionTest.php diff --git a/sculpin/phpstan.neon.dist b/sculpin/phpstan.neon.dist new file mode 100644 index 000000000..730e44767 --- /dev/null +++ b/sculpin/phpstan.neon.dist @@ -0,0 +1,7 @@ +parameters: + level: 9 + paths: + - src + - tests +includes: + - phpstan-baseline.neon diff --git a/sculpin/phpunit.xml.dist b/sculpin/phpunit.xml.dist new file mode 100644 index 000000000..5d7855402 --- /dev/null +++ b/sculpin/phpunit.xml.dist @@ -0,0 +1,8 @@ + + + + + tests + + + diff --git a/sculpin/run b/sculpin/run new file mode 100755 index 000000000..81ad6a58c --- /dev/null +++ b/sculpin/run @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs. + +set -o errexit +set -o nounset +set -o pipefail + +PATH="${PATH}:./vendor/bin" + +# Generate the site. +function generate { + local args=() + + if [[ "${APP_ENV:-}" == "prod" ]]; then + args=(--env="prod") + else + args=(--server --watch) + fi + + sculpin generate "${args[@]}" "${@}" +} + +function help { + printf "%s [args]\n\nTasks:\n" "${0}" + + compgen -A function | grep -v "^_" | cat -n + + printf "\nExtended help:\n Each task has comments for general usage\n" +} + +# Start the project. +function start { + sculpin generate --server --watch "${@}" +} + +# Include any local tasks. +# https://stackoverflow.com/a/6659698 +[[ -e "${BASH_SOURCE%/*}/run.local" ]] && source "${BASH_SOURCE%/*}/run.local" + +TIMEFORMAT="Task completed in %3lR" +time "${@:-help}" + +# vim: ft=bash diff --git a/sculpin/run.local b/sculpin/run.local new file mode 100755 index 000000000..4a3e6c796 --- /dev/null +++ b/sculpin/run.local @@ -0,0 +1,114 @@ +#!/usr/bin/env bash + +function ci:build { + APP_ENV=prod nix develop --command ./run generate +} + +function ci:install { + nix develop --command composer install +} + +function ci:test { + nix develop --command ./run test --testdox --colors=always +} + +function clean { + rm -fr output_*/ source/build/ +} + +# Create a new daily email. +function create-daily { + local date="${1}" + local title="${2}" + + if [ "${date}" == "next" ]; then + next_date=$(ls -1 source/_daily_emails | tail -n 1 | tr -d '.md' | xargs -I {} date +%Y-%m-%d -d '{} +1 day') + else + next_date="${date}" + fi + + filepath="source/_daily_emails/${next_date}.md" + + shift 1 + + # Generate the title and slug. + title="${*}" + slug=$(echo "${title}" | \ + tr '[:upper:]' '[:lower:]' | \ + sed 's/[^a-z0-9]/-/g' | \ + sed 's/\-\-+/-/g' | \ + sed 's/^\-//;s/\-$//') + + # Create the file. + cp -f --no-clobber resources/daily-email-stub.md "${filepath}" + + date=$(date -d "${next_date}" +%Y-%m-%d) + day=$(date -d "${next_date}" +%d) + month=$(date -d "${next_date}" +%m) + year=$(date -d "${next_date}" +%Y) + + # Replace the placeholders. + sed -i "s/{{ date }}/${date}/" "${filepath}" + sed -i "s/{{ title }}/${title}/" "${filepath}" + sed -i "s#{{ permalink }}#daily/${year}/${month}/${day}/${slug}#" "${filepath}" + + # Create a commit with the appropriate date in the message + git add "${filepath}" + git commit --quiet -m "Add daily email for $(date -d "${next_date}" +%d/%m/%y)" + + echo "${filepath}" +} + +# Build CSS assets, this is meant to be run within the `assets` directory. +function npm:build:css { + local args=() + + if [[ "${NODE_ENV:-}" == "production" ]]; then + args=(--minify) + else + args=(--watch) + fi + + cd assets || exit + + tailwindcss \ + --config tailwind.config.ts \ + --input css/tailwind.css \ + --output ../source/build/tailwind.css "${args[@]}" +} + +function setup { + git submodule update --recursive --init + git submodule update --recursive --remote || true + + composer install + (cd assets && pnpm install) + + (cd assets && NODE_ENV=production npm:build:css) + APP_ENV=prod generate +} + +function publish { + git push + + tag-release + git push --tags + + git stash + clean + + # export NODE_ENV=production + # (cd assets && npm:build:css) + APP_ENV=prod generate + + rsync --archive --verbose --compress --update --delete \ + output_prod/ ssh.oliverdavies.uk:/var/www/vhosts/website-sculpin + + git stash pop +} + +function test { + phpunit "${@}" +} + +# vim: ft=bash diff --git a/sculpin/source/.htaccess b/sculpin/source/.htaccess new file mode 100644 index 000000000..fe8755ffc --- /dev/null +++ b/sculpin/source/.htaccess @@ -0,0 +1,445 @@ +Options +FollowSymLinks -MultiViews + +RewriteEngine on + +# Redirect all users to access the site WITH the 'www.' prefix. +RewriteCond %{HTTP_HOST} . +RewriteCond %{HTTP_HOST} !^www\. [NC] +RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + +# Remove trailing slashes from directories. +DirectorySlash Off +RewriteCond %{REQUEST_FILENAME} -d +RewriteCond %{REQUEST_URI} !/$ +RewriteCond %{REQUEST_FILENAME}/index.html -f +RewriteRule (.*) $1/index.html [L] +RewriteRule ^(.*)/$ /$1 [L,R=301] + +# Remove index.html from URLs. +RewriteCond %{THE_REQUEST} \s/+(.*/)?index\.html[\s?] [NC] +RewriteRule ^(.*)index\.html$ /$1 [L,R=301] + +ErrorDocument 404 /404/index.html + +RewriteRule ^daily/2024/08/15/docblocks-or-annotations$ /daily/2024/08/15/docblocks-or-attributes [R=301] +RewriteRule ^10-useful-drupal-6-modules-i-use-every-project$ /blog/10-useful-drupal-6-modules [R=301] +RewriteRule ^2010/04/05/styling-drupal-6s-taxonomy-lists-with-php-css-and-jquery$ /blog/style-drupal-6s-taxonomy-lists-php-css-jquery [R=301] +RewriteRule ^2010/04/28/using-imagecache-and-imagecrop-for-my-portfolio$ /blog/using-imagecache-imagecrop-my-portfolio [R=301] +RewriteRule ^2010/05/29/importing-images-using-the-imagefieldimport-module$ /blog/quickly-import-multiples-images-using-imagefieldimport-module [R=301] +RewriteRule ^2010/06/23/creating-a-block-of-social-media-icons-using-cck-views-and-nodequeue$ /blog/create-block-social-media-icons-using-cck-views-nodequeue [R=301] +RewriteRule ^2010/07/05/thanks$ /blog/thanks [R=301] +RewriteRule ^2010/08/17/create-a-better-photo-gallery-in-drupal-part-2$ /blog/create-better-photo-gallery-drupal-part-2 [R=301] +RewriteRule ^2014/05/21/git-format-patch$ /blog/git-format-patch-your-friend [R=301] +RewriteRule ^2PxmyqP$ /articles/examples-of-laravel-collections-in-drupal [R=301] +RewriteRule ^39CoG$ /articles/drupalcamp-london-testing-workshop [R=301] +RewriteRule ^3eGQr$ https://github.com/howToCodeWell/howToCodeWellFM/blob/c927e0b3589f1d7375002f7fd70f0bfc9fc90449/composer.json#L17 [R=301] +RewriteRule ^6UhLN$ https://github.com/opdavies/sculpin-twig-markdown-bundle/pull/1 [R=301] +RewriteRule ^6i3YZ$ https://www.youtube.com/watch?v=vUK5sEbd-dk [R=301] +RewriteRule ^9rv0Z$ https://www.drupal.org/project/override_node_options/issues/3109852 [R=301] +RewriteRule ^BhMZi$ https://git.drupalcode.org/search?utf8=%E2%9C%93&snippets=&scope=&repository_ref=8.x-1.x&search=baz&project_id=23203 [R=301] +RewriteRule ^NBi5h$ https://git.drupalcode.org/search?utf8=%E2%9C%93&search=bar&group_id=&project_id=23203&search_code=true&repository_ref=8.x-1.x&nav_source=navbar [R=301] +RewriteRule ^P5KQ5$ https://www.npmjs.com/package/tailwindcss-skip-link [R=301] +RewriteRule ^S8ZDA$ /articles/rebuilding-bartik-with-vuejs-tailwind-css-part-2 [R=301] +RewriteRule ^Wh48P$ https://github.com/opdavies/oliverdavies.uk/blob/master/source/_partials/talk/video.html.twig [R=301] +RewriteRule ^XbzS2$ https://github.com/opdavies/gmail-filter-builder [R=301] +RewriteRule ^YK1VH$ /articles/psr4-autoloading-test-cases-drupal-7 [R=301] +RewriteRule ^Yil$ https://drupalcamp.london/tickets/training [R=301] +RewriteRule ^about$ / [R=301] +RewriteRule ^about/cv$ /cv [R=301] +RewriteRule ^about/speaker$ /speaker [R=301] +RewriteRule ^about/speaker-information$ /speaker-information [R=301] +RewriteRule ^acquia-certifications$ https://certification.acquia.com/registry?fname=Oliver&lname=Davies&city=&state=&country=United+Kingdom&org=&exam=All [R=301] +RewriteRule ^acquia-certified$ https://certification.acquia.com/?fname=Oliver&lname=Davies [R=301] +RewriteRule ^ansible$ https://galaxy.ansible.com/opdavies [R=301] +RewriteRule ^ansible-molecule$ /articles/test-driven-ansible-role-development-molecule [R=301] +RewriteRule ^ansistrano-code$ https://github.com/opdavies/dransible [R=301] +RewriteRule ^ansistrano-demo$ https://www.youtube.com/watch?v=PLS4ET7FAcU [R=301] +RewriteRule ^ansistrano-slides$ /presentations/deploying-php-ansible-ansistrano [R=301] +RewriteRule ^archive/2022/10/20/run-vs-task-runner$ /archive/2022/10/19/run-vs-task-runners [R=301] +RewriteRule ^atNOQ$ https://youtu.be/r41dkD2EOo8 [R=301] +RewriteRule ^automatically-updating-talk-created-date$ https://gist.github.com/opdavies/4e75e1753d8603113f07f8264bb783d6 [R=301] +RewriteRule ^blog.xml$ /rss.xml [R=301] +RewriteRule ^blog/10-useful-drupal-6-modules$ /blog/useful-drupal-6-modules [R=301] +RewriteRule ^blog/10-years-working-full-time-drupal$ /blog/10-years-working-full-time-drupal-php [R=301] +RewriteRule ^blog/2010/04/05/style-drupal-6s-taxonomy-lists-php-css-and-jquery$ /blog/style-drupal-6s-taxonomy-lists-php-css-and-jquery [R=301] +RewriteRule ^blog/2010/04/05/styling-drupal-6s-taxonomy-lists-with-php-css-and-jquery$ /blog/style-drupal-6s-taxonomy-lists-php-css-jquery [R=301] +RewriteRule ^blog/2010/04/28/using-imagecache-and-imagecrop-my-portfolio$ /blog/using-imagecache-and-imagecrop-my-portfolio [R=301] +RewriteRule ^blog/2010/05/06/conditional-email-addresses-webform$ /blog/conditional-email-addresses-webform [R=301] +RewriteRule ^blog/2010/05/10/quickly-create-zen-subthemes-using-zenophile$ /blog/quickly-create-zen-subthemes-using-zenophile [R=301] +RewriteRule ^blog/2010/05/25/create-slideshow-multiple-images-using-fancy-slide$ /blog/create-slideshow-multiple-images-using-fancy-slide [R=301] +RewriteRule ^blog/2010/05/29/quickly-import-multiples-images-using-imagefieldimport-module$ /blog/quickly-import-multiples-images-using-imagefieldimport-module [R=301] +RewriteRule ^blog/2010/06/02/improve-jpg-quality-imagecache-and-imageapi$ /blog/improve-jpg-quality-imagecache-and-imageapi [R=301] +RewriteRule ^blog/2010/06/23/create-block-social-media-icons-using-cck-views-and-nodequeue$ /blog/create-block-social-media-icons-using-cck-views-and-nodequeue [R=301] +RewriteRule ^blog/2010/06/25/10-useful-drupal-6-modules$ /blog/10-useful-drupal-6-modules [R=301] +RewriteRule ^blog/2010/06/28/create-flickr-photo-gallery-using-feeds-cck-and-views$ /blog/create-flickr-photo-gallery-using-feeds-cck-and-views [R=301] +RewriteRule ^blog/2010/07/01/change-content-type-multiple-nodes-using-sql$ /blog/change-content-type-multiple-nodes-using-sql [R=301] +RewriteRule ^blog/2010/07/02/create-virtual-hosts-mac-os-x-using-virtualhostx$ /blog/create-virtual-hosts-mac-os-x-using-virtualhostx [R=301] +RewriteRule ^blog/2010/07/07/add-taxonomy-term-multiple-nodes-using-sql$ /blog/add-taxonomy-term-multiple-nodes-using-sql [R=301] +RewriteRule ^blog/2010/07/07/quickly-adding-taxonomy-term-multiple-nodes-using-sql$ /blog/add-taxonomy-term-multiple-nodes-using-sql [R=301] +RewriteRule ^blog/2010/07/12/overview-teleport-module$ /blog/review-teleport-module [R=301] +RewriteRule ^blog/2010/07/12/review-teleport-module$ /blog/review-teleport-module [R=301] +RewriteRule ^blog/2010/08/10/review-adminhover-module$ /blog/review-adminhover-module [R=301] +RewriteRule ^blog/2010/08/11/create-better-photo-gallery-drupal-part-1$ /blog/create-better-photo-gallery-drupal-part-1 [R=301] +RewriteRule ^blog/2010/08/11/how-create-better-photo-gallery-drupal-part-1$ /blog/create-better-photo-gallery-drupal-part-1 [R=301] +RewriteRule ^blog/2010/08/17/create-better-photo-gallery-drupal-part-2$ /blog/create-better-photo-gallery-drupal-part-2 [R=301] +RewriteRule ^blog/2010/08/20/review-image-caption-module$ /blog/review-image-caption-module [R=301] +RewriteRule ^blog/2010/09/26/south-wales-drupal-user-group$ /blog/south-wales-drupal-user-group [R=301] +RewriteRule ^blog/2010/10/10/create-and-apply-patches$ /blog/create-and-apply-patches [R=301] +RewriteRule ^blog/2010/10/13/create-better-photo-gallery-drupal-part-3$ /blog/create-better-photo-gallery-drupal-part-3 [R=301] +RewriteRule ^blog/2010/10/22/create-better-photo-gallery-drupal-part-21$ /blog/create-better-photo-gallery-drupal-part-21 [R=301] +RewriteRule ^blog/2010/11/04/use-regular-expressions-search-and-replace-coda-or-textmate$ /blog/use-regular-expressions-search-and-replace-coda-or-textmate [R=301] +RewriteRule ^blog/2011/02/14/easily-embed-typekit-fonts-your-drupal-website$ /blog/easily-embed-typekit-fonts-your-drupal-website [R=301] +RewriteRule ^blog/2011/03/15/display-number-facebook-fans-php$ /blog/display-number-facebook-fans-php [R=301] +RewriteRule ^blog/2011/03/31/proctor-stevenson$ /blog/proctor-stevenson [R=301] +RewriteRule ^blog/2011/05/20/proctors-hosting-next-drupal-meetup$ /blog/proctors-hosting-next-drupal-meetup [R=301] +RewriteRule ^blog/2011/05/23/imagefield-import-archive$ /blog/imagefield-import-archive [R=301] +RewriteRule ^blog/2011/08/28/create-multigroups-drupal-7-using-field-collections$ /blog/create-multigroups-drupal-7-using-field-collections [R=301] +RewriteRule ^blog/2011/10/19/install-and-configure-subversion-svn-server-ubuntu$ /blog/install-and-configure-subversion-svn-server-ubuntu [R=301] +RewriteRule ^blog/2011/10/install-and-configure-subversion-svn-server-ubuntu$ /blog/how-install-configure-subversion-svn-server-ubuntu [R=301] +RewriteRule ^blog/2012/01/04/site-upgraded-drupal-7$ /blog/site-upgraded-drupal-7 [R=301] +RewriteRule ^blog/2012/02/01/use-authorize-keys-create-passwordless-ssh-connection$ /blog/use-authorized-keys-create-passwordless-ssh-connection [R=301] +RewriteRule ^blog/2012/04/16/create-omega-subtheme-less-css-preprocessor-using-omega-tools-and-drush$ /blog/create-omega-subtheme-less-css-preprocessor-using-omega-tools-and-drush [R=301] +RewriteRule ^blog/2012/04/17/installing-nagios-centos$ /blog/installing-nagios-centos [R=301] +RewriteRule ^blog/2012/04/19/adding-custom-theme-templates-drupal-7$ /blog/adding-custom-theme-templates-drupal-7 [R=301] +RewriteRule ^blog/2012/04/adding-custom-theme-templates-drupal-7$ /blog/adding-custom-theme-templates-drupal-7 [R=301] +RewriteRule ^blog/2012/05/23/add-date-popup-calendar-custom-form$ /blog/add-date-popup-calendar-custom-form [R=301] +RewriteRule ^blog/2012/05/23/checkout-specific-revision-svn-command-line$ /blog/checkout-specific-revision-svn-command-line [R=301] +RewriteRule ^blog/2012/05/23/forward-one-domain-another-using-mod-rewrite-and-htaccess$ /blog/forward-one-domain-another-using-mod-rewrite-and-htaccess [R=301] +RewriteRule ^blog/2012/05/23/forward-one-domain-another-using-modrewrite-and-htaccess$ /blog/forward-one-domain-another-using-modrewrite-htaccess [R=301] +RewriteRule ^blog/2012/05/23/prevent-apache-displaying-text-files-within-web-browser$ /blog/prevent-apache-displaying-text-files-within-web-browser [R=301] +RewriteRule ^blog/2012/05/23/writing-info-file-drupal-7-theme$ /blog/writing-info-file-drupal-7-theme [R=301] +RewriteRule ^blog/2012/05/24/dividing-drupals-process-and-preprocess-functions-separate-files$ /blog/dividing-drupals-process-and-preprocess-functions-separate-files [R=301] +RewriteRule ^blog/2012/05/forward-one-domain-another-using-modrewrite-and-htaccess$ /blog/forward-one-domain-another-using-modrewrite-htaccess [R=301] +RewriteRule ^blog/2012/07/12/my-new-drupal-modules$ /blog/my-new-drupal-modules [R=301] +RewriteRule ^blog/2012/07/14/install-nomensa-media-player-drupal$ /blog/install-nomensa-media-player-drupal [R=301] +RewriteRule ^blog/2012/07/27/writing-article-linux-journal$ /blog/writing-article-linux-journal [R=301] +RewriteRule ^blog/2012/07/install-and-configure-nomensa-accessible-media-player-drupal$ /blog/install-configure-nomensa-accessible-media-player-drupal [R=301] +RewriteRule ^blog/2012/07/nomensa-accessible-media-player-drupal$ /blog/install-configure-nomensa-accessible-media-player-drupal [R=301] +RewriteRule ^blog/2012/08/18/display-custom-menu-drupal-7-theme-template-file$ /blog/display-custom-menu-drupal-7-theme-template-file [R=301] +RewriteRule ^blog/2012/09/06/reflections-speaking-unifieddiff$ /blog/reflections-speaking-unifieddiff [R=301] +RewriteRule ^blog/2012/10/25/my-sublime-text-2-settings$ /blog/my-sublime-text-2-settings [R=301] +RewriteRule ^blog/2012/11/15/accessible-bristol-site-launched$ /blog/accessible-bristol-site-launched [R=301] +RewriteRule ^blog/2012/11/17/open-sublime-text-2-mac-os-x-command-line$ /blog/open-sublime-text-2-mac-os-x-command-line [R=301] +RewriteRule ^blog/2012/12/06/use-sass-and-compass-drupal-7-using-sassy$ /blog/use-sass-and-compass-drupal-7-using-sassy [R=301] +RewriteRule ^blog/2012/12/use-sass-and-compass-drupal-7-using-sassy$ /blog/use-sass-and-compass-drupal-7-using-sassy [R=301] +RewriteRule ^blog/2013/01/09/checking-if-user-logged-drupal-right-way$ /blog/checking-if-user-logged-drupal-right-way [R=301] +RewriteRule ^blog/2013/02/16/creating-and-using-custom-tokens-drupal-7$ /blog/creating-and-using-custom-tokens-drupal-7 [R=301] +RewriteRule ^blog/2013/02/creating-and-using-custom-tokens-drupal-7$ /blog/creating-using-custom-tokens-drupal-7 [R=301] +RewriteRule ^blog/2013/03/02/quickest-way-install-sublime-text-2-ubuntu$ /blog/quickest-way-install-sublime-text-2-ubuntu [R=301] +RewriteRule ^blog/2013/04/20/leaving-nomensa-joining-precedent$ /blog/leaving-nomensa-joining-precedent [R=301] +RewriteRule ^blog/2013/04/27/display-git-branch-or-tag-names-your-bash-prompt$ /blog/display-git-branch-or-tag-names-your-bash-prompt [R=301] +RewriteRule ^blog/2013/04/display-git-branch-or-tag-names-your-bash-prompt$ /blog/display-git-branch-or-tag-names-your-bash-prompt [R=301] +RewriteRule ^blog/2013/06/13/some-useful-links-using-simpletest-drupal$ /blog/some-useful-links-using-simpletest-drupal [R=301] +RewriteRule ^blog/2013/07/17/creating-local-and-staging-sites-drupals-domain-module-enabled$ /blog/creating-local-and-staging-sites-drupals-domain-module-enabled [R=301] +RewriteRule ^blog/2013/07/26/going-drupalcon$ /blog/going-drupalcon [R=301] +RewriteRule ^blog/2013/09/06/create-a-zen-sub-theme-using-drush$ /blog/create-a-zen-sub-theme-using-drush [R=301] +RewriteRule ^blog/2013/09/create-zen-sub-theme-using-drush$ /blog/create-zen-sub-theme-using-drush [R=301] +RewriteRule ^blog/2013/11/19/dont-bootstrap-drupal-use-drush$ /blog/dont-bootstrap-drupal-use-drush [R=301] +RewriteRule ^blog/2013/11/27/useful-vagrant-commands$ /blog/useful-vagrant-commands [R=301] +RewriteRule ^blog/2013/11/dont-bootstrap-drupal-use-drush$ /blog/dont-bootstrap-drupal-use-drush [R=301] +RewriteRule ^blog/2013/12/24/quickly-apply-patches-using-git-and-curl-or-wget$ /blog/quickly-apply-patches-using-git-and-curl-or-wget [R=301] +RewriteRule ^blog/2013/12/31/download-different-versions-drupal-drush$ /blog/download-different-versions-drupal-drush [R=301] +RewriteRule ^blog/2013/12/quickly-apply-patches-using-git-and-curl-or-w$ /blog/quickly-apply-patches-using-git-curl-or-wget [R=301] +RewriteRule ^blog/2014/01/15/some-useful-git-aliases$ /blog/some-useful-git-aliases [R=301] +RewriteRule ^blog/2014/02/09/drupalcamp-london-2014$ /blog/drupalcamp-london-2014 [R=301] +RewriteRule ^blog/2014/03/03/what-git-flow$ /blog/what-git-flow [R=301] +RewriteRule ^blog/2014/05/03/drupal-association$ /blog/drupal-association [R=301] +RewriteRule ^blog/2014/05/06/thanks$ /blog/thanks [R=301] +RewriteRule ^blog/2014/05/21/git-format-patch$ /blog/git-format-patch [R=301] +RewriteRule ^blog/2014/07/02/drush-make-drupalbristol$ /blog/drush-make-drupalbristol [R=301] +RewriteRule ^blog/2014/10/06/fix-vagrant-loading-wrong-virtual-machine$ /blog/fix-vagrant-loading-wrong-virtual-machine [R=301] +RewriteRule ^blog/2014/10/21/updating-features-and-adding-components-using-drush$ /blog/updating-features-and-adding-components-using-drush [R=301] +RewriteRule ^blog/2014/11/18/include-css-fonts-using-sass-each-loop$ /blog/include-css-fonts-using-sass-each-loop [R=301] +RewriteRule ^blog/2014/11/20/using-remote-files-when-developing-locally-with-stage-file-proxy-module$ /blog/using-remote-files-when-developing-locally-with-stage-file-proxy-module [R=301] +RewriteRule ^blog/2014/11/27/pantheon-settings-files$ /blog/pantheon-settings-files [R=301] +RewriteRule ^blog/2014/12/20/include-local-drupal-settings-file-environment-configuration-and-overrides$ /blog/include-local-drupal-settings-file-environment-configuration-and-overrides [R=301] +RewriteRule ^blog/2015/04/03/how-to-define-a-minimum-drupal-core-version$ /blog/how-to-define-a-minimum-drupal-core-version [R=301] +RewriteRule ^blog/2015/06/18/updating-forked-repositories-on-github$ /blog/updating-forked-repositories-on-github [R=301] +RewriteRule ^blog/2015/07/19/sculpin-twig-resources$ /blog/sculpin-twig-resources [R=301] +RewriteRule ^blog/2015/07/21/automating-sculpin-jenkins$ /blog/automating-sculpin-jenkins [R=301] +RewriteRule ^blog/2015/12/22/programmatically-load-an-entityform-in-drupal-7$ /blog/programmatically-load-an-entityform-in-drupal-7 [R=301] +RewriteRule ^blog/2016/02/15/announcing-the-drupal-vm-generator$ /blog/announcing-the-drupal-vm-generator [R=301] +RewriteRule ^blog/2016/05/03/simplifying-drupal-migrations-with-xautoload$ /blog/simplifying-drupal-migrations-with-xautoload [R=301] +RewriteRule ^blog/2016/07/15/building-gmail-filters-with-php$ /blog/building-gmail-filters-with-php [R=301] +RewriteRule ^blog/2016/12/30/drupal-vm-generator-291-released$ /blog/drupal-vm-generator-291-released [R=301] +RewriteRule ^blog/2017/01/07/easier-sculpin-commands-with-composer-and-npm-scripts$ /blog/easier-sculpin-commands-with-composer-and-npm-scripts [R=301] +RewriteRule ^blog/2017/01/31/nginx-redirects-with-query-string-arguments$ /blog/nginx-redirects-with-query-string-arguments [R=301] +RewriteRule ^blog/2017/05/05/fixing-drupal-simpletest-docker$ /blog/2017/05/05/fixing-drupal-simpletest-issues-inside-docker-containers [R=301] +RewriteRule ^blog/2017/05/05/fixing-drupal-simpletest-issues-inside-docker-containers$ /blog/fixing-drupal-simpletest-issues-inside-docker-containers [R=301] +RewriteRule ^blog/2017/05/20/turning-drupal-module-into-feature$ /blog/turning-your-custom-drupal-module-feature [R=301] +RewriteRule ^blog/2017/06/09/introducing-the-drupal-meetups-twitterbot$ /blog/introducing-the-drupal-meetups-twitterbot [R=301] +RewriteRule ^blog/2017/07/13/publishing-sculpin-sites-with-github-pages$ /blog/publishing-sculpin-sites-github-pages [R=301] +RewriteRule ^blog/2017/11/07/tdd-test-driven-drupal$ /blog/tdd-test-driven-drupal [R=301] +RewriteRule ^blog/2017/11/07/writing-drupal-module-test-driven-development-tdd$ /blog/2017/11/07/tdd-test-driven-drupal [R=301] +RewriteRule ^blog/2018/01/30/drupalcamp-bristol-2018$ /blog/drupalcamp-bristol-2018 [R=301] +RewriteRule ^blog/2018/02/05/using-tailwind-css-in-your-drupal-theme$ /blog/using-tailwind-css-in-your-drupal-theme [R=301] +RewriteRule ^blog/2018/02/27/looking-forward-to-drupalcamp-london$ /blog/looking-forward-to-drupalcamp-london [R=301] +RewriteRule ^blog/2018/02/27/queuing-private-messages-in-drupal-8$ /blog/queuing-private-messages-in-drupal-8 [R=301] +RewriteRule ^blog/2018/02/28/building-the-new-phpsw-website$ /blog/building-the-new-phpsw-website [R=301] +RewriteRule ^blog/2018/03/02/yay-the-mediacurrent-contrib-half-hour-is-back$ /blog/yay-the-mediacurrent-contrib-half-hour-is-back [R=301] +RewriteRule ^blog/2018/03/04/tweets-from-drupalcamp-london$ /blog/tweets-from-drupalcamp-london [R=301] +RewriteRule ^blog/2018/04/23/back-to-the-future-git-diff-apply$ /blog/back-future-gits-diff-apply-commands [R=301] +RewriteRule ^blog/2018/05/06/creating-a-custom-phpunit-command-for-docksal$ /blog/creating-a-custom-phpunit-command-for-docksal [R=301] +RewriteRule ^blog/add-date-popup-calendar-custom-form$ /blog/how-add-date-popup-calendar-custom-form [R=301] +RewriteRule ^blog/adding-methods-decorating-entity-metadata-wrapper$ /blog/decorating-entity-metadata-wrapper-add-refactor-methods [R=301] +RewriteRule ^blog/announcing-drupal-vm-generator$ /blog/announcing-the-drupal-vm-generator [R=301] +RewriteRule ^blog/announcing-the-drupal-vm-config-generator$ /blog/announcing-the-drupal-vm-generator [R=301] +RewriteRule ^blog/back-to-the-future-git-diff-apply$ /blog/back-future-gits-diff-apply-commands [R=301] +RewriteRule ^blog/building-gmail-filters-in-php$ /blog/building-gmail-filters-php [R=301] +RewriteRule ^blog/building-new-phpsw-website$ /blog/building-the-new-phpsw-website [R=301] +RewriteRule ^blog/building-presentation-slides-reveal-js-tailwind-css$ /blog/building-presentation-slides-rst2pdf [R=301] +RewriteRule ^blog/building-speaker-leaderboard-php-south-wales-using-drupal-symfony$ /blog/building-speaker-leaderboard-php-south-wales-drupal-symfony [R=301] +RewriteRule ^blog/create-and-apply-patches$ /blog/how-create-apply-patches [R=301] +RewriteRule ^blog/create-flickr-photo-gallery-using-feeds-cck-and-views$ /blog/create-flickr-photo-gallery-using-feeds-cck-views [R=301] +RewriteRule ^blog/creating-and-using-custom-tokens-drupal-7$ /blog/creating-using-custom-tokens-drupal-7 [R=301] +RewriteRule ^blog/creating-custom-docksal-commands$ /blog/creating-custom-phpunit-command-docksal [R=301] +RewriteRule ^blog/debugging-drupal-commerce-promotions-illiminate-collections$ /blog/debugging-drupal-commerce-illuminate-collections [R=301] +RewriteRule ^blog/decorating-entity-metadata-wrapper-add-add-refactor-methods$ /blog/decorating-entity-metadata-wrapper-add-refactor-methods [R=301] +RewriteRule ^blog/dev-book-club-refactoring-chapter-1$ /blog/dev-book-club-notes-refactoring-chapter-1 [R=301] +RewriteRule ^blog/dividing-drupals-process-preprocess-functions-separate-files$ /blog/dividing-drupals-process-and-preprocess-functions-separate-files [R=301] +RewriteRule ^blog/drupal-8-commerce-fixing-no-such-customer-error-on-checkout$ /drupal-8-commerce-fixing-error-on-user-checkout [R=301] +RewriteRule ^blog/drupal-8-commerce-fixing-no-such-customer-error-user-checkout /drupal-8-commerce-fixing-error-on-user-checkout [R=301] +RewriteRule ^blog/drupal-vm-generator-291-released$ /blog/drupal-vm-generator-updates [R=301] +RewriteRule ^blog/drupalcamp-london-2019-tickets$ /blog/drupalcamp-london-2019-tickets-available-call-sessions [R=301] +RewriteRule ^blog/drush-make-drupalbristol$ /presentations/drush-make-drupalbristol [R=301] +RewriteRule ^blog/easier-git-repository-cloning-with-insteadof$ /blog/easier-git-repository-cloning-insteadof [R=301] +RewriteRule ^blog/easier-sculpin-commands-with-composer-and-npm-scripts$ /blog/easier-sculpin-commands-composer-npm-scripts [R=301] +RewriteRule ^blog/editing-meetup-videos-kdenlive$ /blog/editing-meetup-videos-linux-kdenlive [R=301] +RewriteRule ^blog/examples-of-laravel-collections-in-drupal$ /blog/using-laravel-collections-drupal [R=301] +RewriteRule ^blog/experimenting-with-events-in-drupal-8$ /blog/experimenting-events-drupal-8 [R=301] +RewriteRule ^blog/fix-vagrant-loading-wrong-virtual-machine$ /blog/how-fix-vagrant-loading-wrong-virtual-machine [R=301] +RewriteRule ^blog/fixing-drupal-simpletest-docker$ /blog/fixing-drupal-simpletest-issues-inside-docker-containers [R=301] +RewriteRule ^blog/forward-one-domain-another-using-modrewrite-and-htaccess$ /blog/forward-one-domain-another-using-modrewrite-htaccess [R=301] +RewriteRule ^blog/forward-one-domain-another-using-modrewrite-and-htaccess$ /blog/forward-one-domain-another-using-modrewrite-htaccess [R=301] +RewriteRule ^blog/git-format-patch$ /blog/git-format-patch-your-friend [R=301] +RewriteRule ^blog/how-easily-embed-typekit-fonts-your-drupal-website$ /blog/easily-embed-typekit-fonts-your-drupal-website [R=301] +RewriteRule ^blog/how-split-new-drupal-contrib-project-within-another-repository$ /blog/splitting-new-drupal-project-from-repo [R=301] +RewriteRule ^blog/how-style-drupal-6s-taxonomy-lists-php-css-and-jquery$ /blog/style-drupal-6s-taxonomy-lists-php-css-jquery [R=301] +RewriteRule ^blog/include-local-drupal-settings-file-environment-configuration-overrides$ /blog/include-local-drupal-settings-file-environment-configuration-and-overrides [R=301] +RewriteRule ^blog/install-and-configure-subversion-svn-server-ubuntu$ /blog/how-install-configure-subversion-svn-server-ubuntu [R=301] +RewriteRule ^blog/live-blogging-symfonylive-london$ /blog/live-blogging-symfonylive-london-2019 [R=301] +RewriteRule ^blog/minimum-core-version$ /blog/how-define-minimum-drupal-core-version [R=301] +RewriteRule ^blog/nginx-redirects-with-query-string-arguments$ /blog/nginx-redirects-query-string-arguments [R=301] +RewriteRule ^blog/null-users-and-system-users-in-drupal$ /blog/null-users-system-users-drupal [R=301] +RewriteRule ^blog/overridding-phpcs-configuration-drupal-ci$ /blog/overriding-phpcs-configuration-drupal-ci [R=301] +RewriteRule ^blog/pantheon-settings-files$ /blog/include-environment-specific-settings-files-pantheon [R=301] +RewriteRule ^blog/pdfpc-pdf-presenter-console-notes$ /blog/presenting-pdf-slides-using-pdfpc-pdf-presenter-console [R=301] +RewriteRule ^blog/php-apps-subdirectory-nginx$ /blog/how-put-your-php-application-subdirectory-another-site-nginx [R=301] +RewriteRule ^blog/presenting-tailwind-css-ansible-cms-philly$ /blog/presenting-on-tailwind-css-and-ansible-at-cms-philly [R=301] +RewriteRule ^blog/programmatically-load-(an-)?entityform-(in-)?drupal-7$ /blog/entityform [R=301] +RewriteRule ^blog/published-my-first-docker-images-docker-hub$ /blog/published-my-first-docker-images-docker-hub-adr-tools-sculpin-rst2pdf [R=301] +RewriteRule ^blog/publishing-sculpin-sites-(with-)?github-pages$ /blog/publishing-sculpin-sites-github-pages [R=301] +RewriteRule ^blog/queuing-private-messages-in-drupal-8$ /blog/queuing-private-messages-drupal-8 [R=301] +RewriteRule ^blog/quick-project-switching-in-phpstorm$ /blog/quick-project-switching-phpstorm [R=301] +RewriteRule ^blog/quickly-apply-patches-using-git-and-curl-or-wget$ /blog/quickly-apply-patches-using-git-curl-or-wget [R=301] +RewriteRule ^blog/rebuilding-bartik-with-vuejs-tailwind-css$ /blog/rebuilding-bartik-drupals-default-theme-vuejs-tailwind-css [R=301] +RewriteRule ^blog/rebuilding-bartik-with-vuejs-tailwind-css-part-2$ /blog/rebuilding-bartik-drupals-default-theme-vuejs-tailwind-css-part-2 [R=301] +RewriteRule ^blog/rebuilding-uis-tailwind-css$ /blog/uis-ive-rebuilt-tailwind-css [R=301] +RewriteRule ^blog/restructuring-my-tailwindjs-config-files$ /blog/restructuring-my-tailwindjs-configuration-files [R=301] +RewriteRule ^blog/retrieving-profile-data-user-using-entity-metadata-wrapper$ /blog/cleanly-retrieving-user-profile-data-using-entity-metadata-wrapper [R=301] +RewriteRule ^blog/running-drupal-with-symfony-local-server$ /blog/running-drupal-88-symfony-local-server [R=301] +RewriteRule ^blog/running-phpunit-tests-docksal-phpstorm$ /blog/how-run-drupal-8-phpunit-tests-within-docksal-phpstorm [R=301] +RewriteRule ^blog/simplifying-drupal-migrations-with-xautoload$ /blog/simplifying-drupal-migrations-xautoload [R=301] +RewriteRule ^blog/speaking-drupalcon-barcelona-2020$ /blog/speaking-drupalcon-europe-2020 [R=301] +RewriteRule ^blog/speaking-during-lockdown$ /blog/speaking-remotely-during-covid-19 [R=301] +RewriteRule ^blog/speaking-remotely-during-lockdown$ /blog/speaking-remotely-during-covid-19 [R=301] +RewriteRule ^blog/style-drupal-6s-taxonomy-lists-php-css-jquery$ /blog/style-drupal-6s-taxonomy-lists-php-css-and-jquery [R=301] +RewriteRule ^blog/survey-results-my-drupalcon-europe-session$ /blog/survey-results-my-drupalcon-europe-session-test-driven-drupal [R=301] +RewriteRule ^blog/system-users-null-users$ /blog/null-users-and-system-users-in-drupal [R=301] +RewriteRule ^blog/test-driven-drupal-gitstore-leanpub$ /blog/test-driven-drupal-on-gitstore-leanpub [R=301] +RewriteRule ^blog/test-driven-drupal-presentation-drupalcon-europe-0$ /blog/test-driven-drupal-presentation-drupalcon-europe [R=301] +RewriteRule ^blog/test-driven-drupal-session-drupalcon-europe$ /blog/test-driven-drupal-presentation-drupalcon-europe [R=301] +RewriteRule ^blog/test-driven-drupal-session-video-drupalcon-europe$ /blog/test-driven-drupal-presentation-drupalcon-europe [R=301] +RewriteRule ^blog/testing-tailwind-css-plugins-with-jest$ /blog/testing-tailwind-css-plugins-jest [R=301] +RewriteRule ^blog/testing-tailwindcss-plugins-with-jest$ /blog/testing-tailwind-css-plugins-jest [R=301] +RewriteRule ^blog/tweets-from-drupalcamp-london$ /blog/tweets-drupalcamp-london [R=301] +RewriteRule ^blog/updating-features-and-adding-components-using-drush$ /blog/updating-features-adding-components-using-drush [R=301] +RewriteRule ^blog/updating-forked-repositories-github$ /blog/updating-forked-github-repos [R=301] +RewriteRule ^blog/use-regular-expressions-search-and-replace-coda-or-textmate$ /blog/use-regular-expressions-search-replace-coda-or-textmate [R=301] +RewriteRule ^log/using-environment-variables-settings-docksal$ /blog/how-use-environment-variables-your-drupal-settings-docksal [R=301] [R=301] +RewriteRule ^blog/using-psr-4-autoloading-your-drupal-7-test-cases$ /blog/psr4-autoloading-test-cases-drupal-7 [R=301] +RewriteRule ^blog/using-tailwind-css-in-your-drupal-theme$ /blog/using-tailwind-css-your-drupal-theme [R=301] +RewriteRule ^blog/using-the-pcss-extension-postcss-webpack-encore$ /blog/using-pcss-extension-postcss-webpack-encore [R=301] +RewriteRule ^blog/weeknotes-june-5th$ /blog/weeknotes-2021-06-05 [R=301] +RewriteRule ^blog/writing-drupal-module-test-driven-development-tdd$ /blog/writing-new-drupal-8-module-using-test-driven-development-tdd [R=301] +RewriteRule ^book$ /test-driven-drupal [R=301] +RewriteRule ^build-configs$ /daily/2024/08/27/build-configs-is-open-source [R=301] +RewriteRule ^calendars?$ https://savvycal.com/opdavies [R=301] +RewriteRule ^cms-philly$ /articles/presenting-on-tailwind-css-and-ansible-at-cms-philly [R=301] +RewriteRule ^code-enigma-interview$ https://blog.codeenigma.com/interview-with-a-drupal-expert-9fcd8e0fad28 [R=301] +RewriteRule ^consulting$ / [R=301] +RewriteRule ^contrib-half-hour$ https://www.youtube.com/playlist?list=PLu-MxhbnjI9rHroPvZO5LEUhr58Yl0j_F [R=301] +RewriteRule ^cv$ /cv.txt [R=301] +RewriteRule ^d0P5z$ /presentations/drupal-8-php-libraries-drupalorg-api [R=301] +RewriteRule ^d7$ /drupal7 [R=301] +RewriteRule ^dcbristol-cfp$ https://www.papercall.io/drupalcamp-bristol-2019 [R=301] +RewriteRule ^dcbristol17-videos$ https://www.youtube.com/playlist?list=PLOwPvExSyLLngtd6R4PUD9MCXa6QL_obA [R=301] +RewriteRule ^dcbristol19-announced$ /articles/drupalcamp-bristol-2019-speakers-sessions-announced [R=301] +RewriteRule ^dclondon-sat$ https://drupalcamp.london/schedule/saturday [R=301] +RewriteRule ^dclondon-sun$ https://drupalcamp.london/schedule/sunday [R=301] +RewriteRule ^dclondon20$ /articles/drupalcamp-london-testing-workshop [R=301] +RewriteRule ^ddev-phpunit-command$ /blog/creating-custom-phpunit-command-ddev [R=301] +RewriteRule ^deploying-php-ansible$ /presentations/deploying-php-ansible-ansistrano [R=301] +RewriteRule ^dks7E$ https://www.youtube.com/watch?v=PLS4ET7FAcU [R=301] +RewriteRule ^do-library$ https://github.com/opdavies/drupalorg-api-php [R=301] +RewriteRule ^do-projects$ https://github.com/opdavies/drupal-module-drupalorg-projects [R=301] +RewriteRule ^docksal-phpunit-phpstorm$ /articles/running-phpunit-tests-docksal-phpstorm [R=301] +RewriteRule ^docksal-posts$ /articles/tags/docksal [R=301] +RewriteRule ^dransible$ https://github.com/opdavies/dransible [R=301] +RewriteRule ^dransible-drupal-9$ /blog/upgrading-dransible-project-drupal-9 [R=301] +RewriteRule ^drupal-bristol-march-19$ https://docs.google.com/presentation/d/1pk9LIN-hHX73kvDdo-lzgmKlAeH33_K_uvI0t7A-rvY/edit?usp=sharing [R=301] +RewriteRule ^drupal-consultant$ /drupal-consulting [R=301] +RewriteRule ^drupal-consulting$ / [R=301] +RewriteRule ^drupal-core-live-stream$ https://www.youtube.com/watch?v=OK4FWwh1gQU [R=301] +RewriteRule ^drupal-core-testing-gate$ https://www.drupal.org/core/gates#testing [R=301] +RewriteRule ^drupal-first-time-issues$ https://www.drupal.org/project/issues/search?text=&projects=&assigned=&submitted=&project_issue_followers=&status%5B%5D=Open&issue_tags_op=%3D&issue_tags=Novice [R=301] +RewriteRule ^drupal-forum-post$ http://www.webmaster-forums.net/webmasters-corner/developing-my-website-using-php-and-mysql#comment-1231537 [R=301] +RewriteRule ^drupal-marketplace-uk$ https://www.drupal.org/drupal-services?offices%5B%5D=24460 [R=301] +RewriteRule ^drupal-meetups-twitterbot$ /articles/introducing-the-drupal-meetups-twitterbot [R=301] +RewriteRule ^drupal-novice-issues$ https://www.drupal.org/project/issues/search?text=&projects=&assigned=&submitted=&project_issue_followers=&status%5B%5D=Open&issue_tags_op=%3D&issue_tags=Novice [R=301] +RewriteRule ^drupal-php-developer$ /drupal-consultant [R=301] +RewriteRule ^drupal-php-developer-consultant-uk$ /drupal-php-developer [R=301] +RewriteRule ^drupal-tailwind-demo$ https://www.youtube.com/watch?v=1eM-Gw6GI4g [R=301] +RewriteRule ^drupal-tailwindcss$ https://www.drupal.org/project/tailwindcss [R=301] +RewriteRule ^drupal-vuejs$ /presentations/decoupling-drupal-vuejs [R=301] +RewriteRule ^drupal7$ /drupal-upgrade [R=301] +RewriteRule ^drupalcamp-london-2019-tickets$ /articles/drupalcamp-london-2019-tickets [R=301] +RewriteRule ^drupalcamp-nyc-training$ https://www.youtube.com/watch?v=3M9c4UUzKm0 [R=301] +RewriteRule ^drupalorg$ https://www.drupal.org/u/opdavies [R=301] +RewriteRule ^drupalorg-project-issues$ https://www.drupal.org/project/issues/search?projects=Override+Node+Options%2C+Tailwind+CSS+Starter+Kit%2C+Block+ARIA+Landmark+Roles%2C+Copyright+Block+module%2C+System+User%2C+Null+User%2C+Collection+class%2C+Pathauto+Menu+Link%2C+Webform+ARIA&project_issue_followers=&status%5B%5D=1&status%5B%5D=13&status%5B%5D=8&status%5B%5D=14&status%5B%5D=15&issue_tags_op=%3D [R=301] +RewriteRule ^drupalversary$ https://github.com/opdavies/drupal-module-drupalversary [R=301] +RewriteRule ^elewant$ https://elewant.com/shepherd/admire/opdavies [R=301] +RewriteRule ^feed$ /rss.xml [R=301] +RewriteRule ^first-drupal-core-issue$ https://www.drupal.org/project/drupal/issues/753898 [R=301] +RewriteRule ^first-npm-package$ https://www.npmjs.com/package/tailwindcss-vuejs [R=301] +RewriteRule ^freeagent$ https://opdavies.freeagent.com [R=301] +RewriteRule ^git-flow$ /presentations/git-flow [R=301] +RewriteRule ^github-sculpin$ https://github.com/opdavies?tab=repositories&q=sculpin [R=301] +RewriteRule ^gitlab$ https://gitlab.com/opdavies [R=301] +RewriteRule ^gitstore$ https://enjoy.gitstore.app/maintainers/opdavies [R=301] +RewriteRule ^gmail-filters$ https://gitlab.com/opdavies/gmail-filters [R=301] +RewriteRule ^images/me-precedent.jpg$ /sites/default/files/images/social-avatar.jpg [R=301] +RewriteRule ^inviqa-tailwind-demo$ https://play.tailwindcss.com/Yfmw8O5UNN [R=301] +RewriteRule ^inviqa-tailwind-notes$ https://gist.github.com/opdavies/e6f0f4938506a6859acf1aca8b4e1a74 [R=301] +RewriteRule ^join-php-south-wales-slack$ https://join.slack.com/t/phpsouthwales/shared_invite/zt-4vuetc43-AvtEK1WqNzp5k1w4yWKOJA [R=301] +RewriteRule ^jy6rW$ https://www.meetup.com/PHP-South-Wales/events/264731393 [R=301] +RewriteRule ^kB6Jd$ /articles/running-drupal-with-symfony-local-server/ [R=301] +RewriteRule ^kmDRA$ https://www.bbc.co.uk/news/uk-46561779 [R=301] +RewriteRule ^leeds-php-drupal-9$ https://www.meetup.com/leedsphp/events/272504993 [R=301] +RewriteRule ^live$ https://www.youtube.com/channel/UCkeK0qF9HHUPQH_fvn4ghqQ [R=301] +RewriteRule ^npm$ https://www.npmjs.com/~opdavies [R=301] +RewriteRule ^oFlkS$ /articles/test-driven-drupal-on-gitstore-leanpub [R=301] +RewriteRule ^oliver-davies-uk-based-drupal-symfony-developer$ /oliver-davies-uk-based-drupal-php-developer [R=301] +RewriteRule ^pair-programming$ /pair [R=301] +RewriteRule ^pair-with-me$ /pair [R=301] +RewriteRule ^pairing$ /pair [R=301] +RewriteRule ^php-ansible$ /presentations/deploying-php-ansible-ansistrano [R=301] +RewriteRule ^presentations/what-is-this-drupal-thing$ /presentations/so-what-is-this-drupal-thing [R=301] +RewriteRule ^qSHAl$ /articles/published-my-first-npm-package/ [R=301] +RewriteRule ^qT1Rb$ https://github.com/opdavies/drupal-meetups-twitterbot [R=301] +RewriteRule ^rebuilding-acquia$ https://rebuilding-acquia.oliverdavies.uk [R=301] +RewriteRule ^rebuilding-bartik$ /articles/rebuilding-bartik-with-vuejs-tailwind-css [R=301] +RewriteRule ^rebuilding-bristol-js$ https://github.com/opdavies/rebuilding-bristol-js [R=301] +RewriteRule ^rebuilding-pantheon$ https://play.tailwindcss.com/LND98XihGI?layout=horizontal [R=301] +RewriteRule ^rebuilding-platformsh$ https://rebuilding-platformsh.oliverdavies.uk [R=301] +RewriteRule ^rebuilding-symfony$ https://github.com/opdavies/rebuilding-symfony [R=301] +RewriteRule ^rk29B$ https://www.meetup.com/PHP-South-Wales/events/268422525 [R=301] +RewriteRule ^roadmap$ /drupal-upgrade [R=301] +RewriteRule ^rss$ /rss.xml [R=301] +RewriteRule ^rst2pdf$ /presentations/building-presenting-slide-decks-rst2pdf [R=301] +RewriteRule ^s9MjJ$ https://symfonycasts.com/screencast/symfony [R=301] +RewriteRule ^sculpin$ /presentations/building-static-websites-sculpin [R=301] +RewriteRule ^sculpin-encore-versioning$ https://github.com/opdavies/oliverdavies.uk/commit/d192b04aefa6e7a21bfc1f2e0fe0a16111e0e8a2 [R=301] +RewriteRule ^sites/default/files/images/social-avatar.$ /images/social-avatar.jpg [R=301] +RewriteRule ^skills$ https://opdavies-skills-tailwindcss.netlify.com/ [R=301] +RewriteRule ^slides-drupal-9$ https://slides-upgrading-to-drupal-9.oliverdavies.uk [R=301] +RewriteRule ^slides-upgrading-to-drupal-9$ https://slides-upgrading-to-drupal-9.oliverdavies.uk [R=301] +RewriteRule ^slides-upgrading-to-drupal-9/index.html$ https://slides-upgrading-to-drupal-9.oliverdavies.uk [R=301] +RewriteRule ^slides-working-with-workspace$ https://slides-working-with-workspace.oliverdavies.uk [R=301] +RewriteRule ^speaker$ /press [R=301] +RewriteRule ^speaker-info$ /speaker [R=301] +RewriteRule ^speaker-information$ /speaker [R=301] +RewriteRule ^speaking-videos$ https://www.youtube.com/playlist?list=PLHn41Ay7w7kfAzczswrANch5oHAPZBlvu [R=301] +RewriteRule ^stream$ https://www.youtube.com/channel/UCkeK0qF9HHUPQH_fvn4ghqQ/live [R=301] +RewriteRule ^subscription$ / [R=301] +RewriteRule ^swap-markdown-parser$ https://github.com/opdavies/sculpin-twig-markdown-bundle-example/tree/swap-markdown-parser [R=301] +RewriteRule ^symfony$ https://connect.symfony.com/profile/opdavies [R=301] +RewriteRule ^symfony-server$ /articles/running-drupal-with-symfony-local-server [R=301] +RewriteRule ^symfonylive$ /articles/live-blogging-symfonylive-london [R=301] +RewriteRule ^symposium$ https://symposiumapp.com/u/opdavies [R=301] +RewriteRule ^tailwind$ /presentations/taking-flight-with-tailwind-css [R=301] +RewriteRule ^tailwind-css-talk$ /presentations/taking-flight-tailwind-css [R=301] +RewriteRule ^tailwind-repos$ https://github.com/opdavies?utf8=%E2%9C%93&tab=repositories&q=tailwindcss [R=301] +RewriteRule ^tailwind-talk$ /presentations/taking-flight-with-tailwind-css [R=301] +RewriteRule ^tailwindcss-demo$ http://tailwindcss-demo.oliverdavies.uk/ [R=301] +RewriteRule ^talks$ /presentations [R=301] +RewriteRule ^talks-offer-tweet$ https://twitter.com/opdavies/status/1250870367712935938 [R=301] +RewriteRule ^talks/2012/09/05/what-is-this-drupal-thing-unified-diff$ /presentations/so-what-is-this-drupal-thing [R=301] +RewriteRule ^talks/2013/07/10/drupal-ldap-swdug$ /presentations/drupal-ldap [R=301] +RewriteRule ^talks/2014/03/01/git-flow-drupalcamp-london-2014$ /presentations/git-flow [R=301] +RewriteRule ^talks/2014/07/02/drush-make-drupalbristol-drupal-bristol$ /presentations/drush-make-drupalbristol [R=301] +RewriteRule ^talks/2014/08/19/drupal-association-swdug$ /presentations/drupal-association [R=301] +RewriteRule ^talks/2015/01/18/drupalorg-2015-drupalcamp-brighton-2015$ /presentations/drupalorg-in-2015-whats-coming-next [R=301] +RewriteRule ^talks/2015/02/28/drupalorg-2015-drupalcamp-london-2015$ /presentations/drupalorg-in-2015-whats-coming-next [R=301] +RewriteRule ^talks/2015/04/08/drupal-8-phpsw$ /presentations/drupal-8 [R=301] +RewriteRule ^talks/2015/07/25/test-drive-twig-with-sculpin-drupalcamp-north-2015$ /presentations/test-drive-twig-with-sculpin [R=301] +RewriteRule ^talks/2015/08/25/dancing-for-drupal-umbristol$ /presentations/dancing-for-drupal [R=301] +RewriteRule ^talks/2015/10/14/sculpin-phpsw$ /presentations/sculpin [R=301] +RewriteRule ^talks/2016/03/05/drupal-8-module-development-drupalcamp-london-2016$ /presentations/getting-started-with-drupal-8-module-development [R=301] +RewriteRule ^talks/2016/03/09/drupal-vm-generator-nwdug$ /presentations/drupal-vm-generator [R=301] +RewriteRule ^talks/2016/04/02/drupal-vm-generator-drupal-bristol$ /presentations/drupal-vm-generator [R=301] +RewriteRule ^talks/2016/06/11/drupal-8-rejoining-the-herd-php-south-coast-2016$ /presentations/drupal-8-rejoining-the-herd [R=301] +RewriteRule ^talks/2016/07/23/drupal-vm-meet-symfony-console-drupalcamp-bristol-2016$ /presentations/drupal-vm-meet-symfony-console [R=301] +RewriteRule ^talks/2016/11/09/drupal-development-with-composer-phpsw$ /presentations/drupal-development-with-composer [R=301] +RewriteRule ^talks/2016/11/17/goodbye-drush-make-hello-composer-drupal-bristol$ /presentations/goodbye-drush-make-hello-composer [R=301] +RewriteRule ^talks/2017/01/18/getting-your-data-into-drupal-8-drupal-bristol$ /presentations/getting-your-data-into-drupal-8 [R=301] +RewriteRule ^talks/2017/03/04/getting-your-data-into-drupal-8-drupalcamp-london-2017$ /presentations/getting-your-data-into-drupal-8 [R=301] +RewriteRule ^talks/ansible-ansistrano$ https://www.oliverdavies.uk/presentations/deploying-php-ansible-ansistrano [R=301] +RewriteRule ^talks/archive$ /presentations [R=301] +RewriteRule ^talks/deploying-php-applications-fabric$ /presentations/deploying-php-fabric [R=301] +RewriteRule ^talks/deploying-php-applications-with-fabric$ /presentations/deploying-php-fabric [R=301] +RewriteRule ^talks/drupal-vm-generator-2$ /presentations/drupal-vm-generator [R=301] +RewriteRule ^talks/drupalorg-2015-2$ /presentations/drupalorg-2015 [R=301] +RewriteRule ^talks/drupalorg-in-2015-whats-coming-next$ /presentations/drupalorg-2015 [R=301] +RewriteRule ^talks/getting-started-with-drupal-8-module-development$ /drupal-8-module-development [R=301] +RewriteRule ^talks/having-fun-drupal-8-php-libraries-drupalorg-api$ /presentations/drupal-8-php-libraries-drupalorg-api [R=301] +RewriteRule ^talks/never-commit-master-introduction-git-flow$ /presentations/git-flow [R=301] +RewriteRule ^talks/sculpin$ /presentations/building-static-websites-sculpin [R=301] +RewriteRule ^talks/tailwind$ /presentations/taking-flight-with-tailwind-css/ [R=301] +RewriteRule ^talks/taking-flight-tailwind-css$ /presentations/taking-flight-with-tailwind-css [R=301] +RewriteRule ^talks/using-laravel-collections-outside-laravel$ /presentations/using-illuminate-collections-outside-laravel [R=301] +RewriteRule ^talks/what-is-this-drupal-thing$ /presentations/so-what-is-this-drupal-thing [R=301] +RewriteRule ^talks/what-is-this-drupal-thing-unified-diff$ /presentations/so-what-is-this-drupal-thing [R=301] +RewriteRule ^talks/working-workspace$ /presentations/working-with-workspace [R=301] +RewriteRule ^tdd-blog$ https://github.com/opdavies/drupal-module-tdd-blog [R=301] +RewriteRule ^tdd-test-driven-drupal$ /presentations/tdd-test-driven-drupal/ [R=301] +RewriteRule ^team-coaching$ / [R=301] +RewriteRule ^test-driven-drupal-book$ /test-driven-drupal [R=301] +RewriteRule ^testing-drupal$ /presentations/tdd-test-driven-drupal [R=301] +RewriteRule ^testing-drupal-intro$ https://inviqa.com/blog/drupal-automated-testing-introduction [R=301] +RewriteRule ^testing-tailwind-plugins$ /articles/testing-tailwindcss-plugins-with-jest [R=301] +RewriteRule ^testing-workshop$ https://github.com/opdavies/workshop-drupal-automated-testing [R=301] +RewriteRule ^testing-workshop-code$ https://github.com/opdavies/workshop-drupal-automated-testing-code [R=301] +RewriteRule ^todoist-filters$ https://gist.github.com/opdavies/6709fbdac5c3babbd94137bcc8b8e3c2 [R=301] +RewriteRule ^twitter-tweaks$ https://github.com/opdavies/chrome-extension-twitter-tweaks [R=301] +RewriteRule ^upgrading-to-drupal-9$ /presentations/upgrading-your-site-drupal-9 [R=301] +RewriteRule ^uxbjV$ https://www.drupal.org/project/copyright_block [R=301] +RewriteRule ^vyTEF$ https://www.npmjs.com/package/tailwindcss-vuejs [R=301] +RewriteRule ^webpack-encore-pcss-regex$ https://regexr.com/51iaf [R=301] +RewriteRule ^wordcamp-bristol-tailwindcss$ https://2019.bristol.wordcamp.org/session/taking-flight-with-tailwind-css [R=301] +RewriteRule ^wordpress-tailwind$ https://github.com/opdavies/wordcamp-bristol-2019 [R=301] +RewriteRule ^work$ /drupal-php-developer [R=301] +RewriteRule ^working-with-workspace$ /presentations/working-with-workspace [R=301] +RewriteRule ^workshop-drupal-testing$ https://github.com/opdavies/workshop-drupal-automated-testing [R=301] +RewriteRule ^workspace-demo$ https://github.com/opdavies/working-with-workspace-demo [R=301] +RewriteRule ^wp-tailwind$ https://wp-tailwind.oliverdavies.uk [R=301] +RewriteRule ^wp-tailwind-repo$ https://github.com/opdavies/wordcamp-bristol-2019 [R=301] +RewriteRule ^wp-tailwind-starter$ https://github.com/opdavies/wordpress-tailwindcss-startker-kit [R=301] +RewriteRule ^wp-tailwind-static$ https://wp-tailwind.oliverdavies.uk [R=301] +RewriteRule ^yXhoS$ /presentations/things-you-should-know-about-php [R=301] + +# ^ewriteCond %{REQUEST_URI}$ !^/archive/?$ +# RewriteRule ^archive/(.*)$$ /daily/$1 [L,R=301] + +RewriteRule ^articles/(.*)$ /blog/$1 [L,R=301] +RewriteRule ^talks/(.*)$ /presentations/$1 [L,R=301] diff --git a/sculpin/source/_includes/about-me.html.twig b/sculpin/source/_includes/about-me.html.twig new file mode 100644 index 000000000..77deb4952 --- /dev/null +++ b/sculpin/source/_includes/about-me.html.twig @@ -0,0 +1,17 @@ +{% import "_macros" as macros %} + +
+

About me

+ +
+
+
+ Picture of Oliver +
+ +
+

I'm an certified Drupal Triple Expert with {{ get_years_of_experience() }} years of experience, a Drupal core contributor, public speaker, live streamer, and host of the Beyond Blocks podcast.

+
+
+
+
diff --git a/sculpin/source/_includes/banner.html.twig b/sculpin/source/_includes/banner.html.twig new file mode 100644 index 000000000..8f5f7f47a --- /dev/null +++ b/sculpin/source/_includes/banner.html.twig @@ -0,0 +1,9 @@ +{% if site.banner_text %} +
+
+
+ {{ site.banner_text|markdown }} +
+
+
+{% endif %} diff --git a/sculpin/source/_includes/button.html.twig b/sculpin/source/_includes/button.html.twig new file mode 100644 index 000000000..6f12c6140 --- /dev/null +++ b/sculpin/source/_includes/button.html.twig @@ -0,0 +1,19 @@ +{% set classes = [ + 'my-4 not-prose', + full_width ? 'flex' : 'inline-flex md:w-auto', + position == 'center' ? 'flex justify-center', +] -%} + + diff --git a/sculpin/source/_includes/callout.html.twig b/sculpin/source/_includes/callout.html.twig new file mode 100644 index 000000000..dd1c1928a --- /dev/null +++ b/sculpin/source/_includes/callout.html.twig @@ -0,0 +1,7 @@ + diff --git a/sculpin/source/_includes/daily-email-form.html.twig b/sculpin/source/_includes/daily-email-form.html.twig new file mode 100644 index 000000000..3b4a58b0d --- /dev/null +++ b/sculpin/source/_includes/daily-email-form.html.twig @@ -0,0 +1,699 @@ + + +
+ {% if title %} +

{{ title }}

+ {% endif %} + + {% set formId = 3546728 %} + {% set uid = 'f0c1d2b57f' %} +
+
+
    +
+ +
+ {% if intro %} +

{{ intro }}

+ {% endif %} + +
+ +
+ +
+ +
+ + + + +
+
+
+
diff --git a/sculpin/source/_includes/daily-emails/most-recent.html.twig b/sculpin/source/_includes/daily-emails/most-recent.html.twig new file mode 100644 index 000000000..4d38439e3 --- /dev/null +++ b/sculpin/source/_includes/daily-emails/most-recent.html.twig @@ -0,0 +1,13 @@ + + +
+

{{ title }}

+ +

Here are the emails I sent this week:

+ + +
diff --git a/sculpin/source/_includes/drupal-association.html.twig b/sculpin/source/_includes/drupal-association.html.twig new file mode 100644 index 000000000..e213d172a --- /dev/null +++ b/sculpin/source/_includes/drupal-association.html.twig @@ -0,0 +1,7 @@ +
+

Work with me and support the Drupal project

+ +
+

5% from any Drupal-related product or service is donated to the Drupal Association.

+
+
diff --git a/sculpin/source/_includes/email-course-form.html.twig b/sculpin/source/_includes/email-course-form.html.twig new file mode 100644 index 000000000..a78bb031a --- /dev/null +++ b/sculpin/source/_includes/email-course-form.html.twig @@ -0,0 +1,672 @@ + + +{% set formId = 5734493 %} +{% set uid = '0b8a47053e' %} +
+
+
    +
+ +
+
+ +
+ +
+ +
+
+
+
diff --git a/sculpin/source/_includes/figure.html.twig b/sculpin/source/_includes/figure.html.twig new file mode 100644 index 000000000..c8de55c1f --- /dev/null +++ b/sculpin/source/_includes/figure.html.twig @@ -0,0 +1,8 @@ +
+ {{ image.alt }} + {% if caption %} +
+ {{ caption }} +
+ {% endif %} +
diff --git a/sculpin/source/_includes/logo.html.twig b/sculpin/source/_includes/logo.html.twig new file mode 100644 index 000000000..8be764240 --- /dev/null +++ b/sculpin/source/_includes/logo.html.twig @@ -0,0 +1,10 @@ + diff --git a/sculpin/source/_includes/main-menu.html.twig b/sculpin/source/_includes/main-menu.html.twig new file mode 100644 index 000000000..3a8518172 --- /dev/null +++ b/sculpin/source/_includes/main-menu.html.twig @@ -0,0 +1,7 @@ + diff --git a/sculpin/source/_includes/message.html.twig b/sculpin/source/_includes/message.html.twig new file mode 100644 index 000000000..f6924a093 --- /dev/null +++ b/sculpin/source/_includes/message.html.twig @@ -0,0 +1,9 @@ +{#
+
+
+

+ Work with me and support the Drupal project. 5% from any Drupal-related product or service is donated to the Drupal Association. +

+
+
+
#} diff --git a/sculpin/source/_includes/podcast/other-episodes.html.twig b/sculpin/source/_includes/podcast/other-episodes.html.twig new file mode 100644 index 000000000..ab609f0ea --- /dev/null +++ b/sculpin/source/_includes/podcast/other-episodes.html.twig @@ -0,0 +1,22 @@ +{% set other_episodes = [] %} + +{% for episode in all_episodes %} + {% if guest in episode.guests and episode.topic is not same as topic %} + {% set other_episodes = other_episodes|merge([episode]) %} + {% endif %} +{% endfor %} + +{% if other_episodes is not empty %} +
+

Other episodes with {{ guest }}

+ +
    + {% for episode in other_episodes %} +
  • + {{ episode.topic }} + - {{ episode.date|date('jS F Y') }} +
  • + {% endfor %} +
+
+{% endif %} diff --git a/sculpin/source/_includes/presentation/events-new.html.twig b/sculpin/source/_includes/presentation/events-new.html.twig new file mode 100644 index 000000000..7bf573563 --- /dev/null +++ b/sculpin/source/_includes/presentation/events-new.html.twig @@ -0,0 +1,46 @@ +
+

Events

+ + + + + + + + + + {% for event in events|sort((a, b) => b.date <=> a.date) %} + + + + + + + {% endfor %} + +
Event nameDateLocationLinks
{{ event.name }} + {% if event.online %} + Online + {% elseif event.location %} + {{ event.location }} + {% endif %} + + {% if event.urls %} + + {% endif %} +
+
diff --git a/sculpin/source/_includes/presentation/events.html.twig b/sculpin/source/_includes/presentation/events.html.twig new file mode 100644 index 000000000..7c2f67c8d --- /dev/null +++ b/sculpin/source/_includes/presentation/events.html.twig @@ -0,0 +1,25 @@ +{% if events %} +
+

Events

+ +
    + {% for event in events|sort((a, b) => b.date <=> a.date) %} +
  • + {% if event.url %} + {{ event.name }} + {% else %} + {{ event.name }} + {% endif %} + + {% if event.location and not event.online %} + in {{ event.location }} + {% endif %} + + - {{ event.date|date('F jS, Y') }} + + {{ event.online ? '(online)' }} +
  • + {% endfor %} +
+
+{% endif %} diff --git a/sculpin/source/_includes/presentation/slides.html.twig b/sculpin/source/_includes/presentation/slides.html.twig new file mode 100644 index 000000000..d15927bb1 --- /dev/null +++ b/sculpin/source/_includes/presentation/slides.html.twig @@ -0,0 +1,15 @@ +{% if speakerdeck.id %} +
+

Slides

+ +
+ + +
+
+{% endif %} diff --git a/sculpin/source/_includes/presentation/video.html.twig b/sculpin/source/_includes/presentation/video.html.twig new file mode 100644 index 000000000..7c84e8fa9 --- /dev/null +++ b/sculpin/source/_includes/presentation/video.html.twig @@ -0,0 +1,20 @@ +{% if video.id %} +
+

Video

+ +
+ {% if video.type == 'vimeo' %} +
+ +
+ {% elseif video.type == 'youtube' %} + {% include 'youtube-video.html.twig' with { id: video.id } %} + {% endif %} +
+
+{% endif %} diff --git a/sculpin/source/_includes/subscription-plans.html.twig b/sculpin/source/_includes/subscription-plans.html.twig new file mode 100644 index 000000000..6775d6c64 --- /dev/null +++ b/sculpin/source/_includes/subscription-plans.html.twig @@ -0,0 +1,26 @@ +{% for plan in plans %} +
+

+ + {{ plan.name }}: + £{{ plan.price|number_format }} per month + +

+ +

{{ plan.tagline }}

+ +
    + {% for feature in plan.features|merge(page.features) %} +
  • {{ feature }}
  • + {% endfor %} +
+ +
+ {% include 'button.html.twig' with { + text: 'Register now for the ' ~ plan.name|lower ~ ' plan', + url: plan.url, + withArrow: true, + } %} +
+
+{% endfor %} diff --git a/sculpin/source/_includes/testimonials.html.twig b/sculpin/source/_includes/testimonials.html.twig new file mode 100644 index 000000000..ceb6560f5 --- /dev/null +++ b/sculpin/source/_includes/testimonials.html.twig @@ -0,0 +1,50 @@ +{% set limit = limit ?? 10 %} +{% set offset = offset ?? 0 %} + +{% set testimonials = site.testimonials %} + +{% if tag is not null %} + {% set testimonials = testimonials|filter(testimonial => tag in testimonial.tags) %} +{% endif %} + +{% if limit > 0 %} + {% set testimonials = testimonials|slice(offset, limit) %} +{% endif %} + +
+

{{ title|default('Testimonials') }}

+ +
+ {% for testimonial in testimonials %} +
+
+
+ {{ testimonial.text|markdown }} +
+ +
+
+ + {% if testimonial.url %} + {{ testimonial.name }} + {% else %} + {{ testimonial.name }} + {% endif %} + + {% if testimonial.title %} + - {{ testimonial.title }} + {% endif %} + + + {% if testimonial.image %} + + Photo of {{ testimonial.name }} + + {% endif %} +
+
+
+
+ {% endfor %} +
+
diff --git a/sculpin/source/_includes/tweet.html.twig b/sculpin/source/_includes/tweet.html.twig new file mode 100644 index 000000000..68bafebce --- /dev/null +++ b/sculpin/source/_includes/tweet.html.twig @@ -0,0 +1,10 @@ +
+ +
diff --git a/sculpin/source/_includes/youtube-video.html.twig b/sculpin/source/_includes/youtube-video.html.twig new file mode 100644 index 000000000..03489bcac --- /dev/null +++ b/sculpin/source/_includes/youtube-video.html.twig @@ -0,0 +1,8 @@ +
+ +
diff --git a/sculpin/source/_layouts/_macros.html.twig b/sculpin/source/_layouts/_macros.html.twig new file mode 100644 index 000000000..a6f7bbd33 --- /dev/null +++ b/sculpin/source/_layouts/_macros.html.twig @@ -0,0 +1,3 @@ +{% macro yearsOfExperience() %} + {{ today|date('Y') - 2007 }} +{% endmacro %} diff --git a/sculpin/source/_layouts/base.html.twig b/sculpin/source/_layouts/base.html.twig new file mode 100644 index 000000000..08f1c2cd7 --- /dev/null +++ b/sculpin/source/_layouts/base.html.twig @@ -0,0 +1,102 @@ + + + + + + + {% if site.features.new_css %} + {% else %} + + {% endif %} + + + + + + + + + + + + + + + + {% if page.blocks.meta_description %} + + {% elseif page.meta.description %} + + {% else %} + + {% endif %} + + {% block head_title %} + {% if page.meta.title %} + {{ page.meta.title }} + + + {% else %} + {{ page.title }} | {{ site.name }} + + + {% endif %} + {% endblock %} + + {% block styles %}{% endblock %} + + + Jump to the navigation menu + +
+ {% include 'banner.html.twig' %} + +
+
+ {% include 'logo.html.twig' %} +
+
+ +
+
+ {% block content_top %}{% endblock %} + +
+ {% if page.url matches "#^/atdc/#" %} +
+
+
+

I'm currently updating this course for Drupal 11. If you find any bugs or have any issues, please let me know. +

+
+
+ {% endif %} + +

+ {% block page_title %}{{ page.title }}{% endblock %} +

+ +
+ {% block content_wrapper %} + {% block content %}{% endblock %} + {% endblock %} +
+
+ + {% block content_bottom %}{% endblock %} +
+ +
+ + + {% include 'main-menu.html.twig' %} +
+
+
+ + {# Add the Mastodon verification link so pages can be verified. #} + + + {% block scripts %}{% endblock %} + + diff --git a/sculpin/source/_layouts/feed.html.twig b/sculpin/source/_layouts/feed.html.twig new file mode 100644 index 000000000..cb0dbe444 --- /dev/null +++ b/sculpin/source/_layouts/feed.html.twig @@ -0,0 +1 @@ +{% block content %}{% endblock %} diff --git a/sculpin/source/_layouts/page.html.twig b/sculpin/source/_layouts/page.html.twig new file mode 100644 index 000000000..d055ba343 --- /dev/null +++ b/sculpin/source/_layouts/page.html.twig @@ -0,0 +1,5 @@ +{% extends 'base' %} + +{% block content_bottom %} + {% include 'about-me.html.twig' %} +{% endblock %} diff --git a/sculpin/source/_layouts/podcast_episode.html.twig b/sculpin/source/_layouts/podcast_episode.html.twig new file mode 100644 index 000000000..a7c164297 --- /dev/null +++ b/sculpin/source/_layouts/podcast_episode.html.twig @@ -0,0 +1,71 @@ +{% extends 'page' %} + +{% block meta_description -%} + Discussing {{ page.topic }} with {{ page.guests|join(' and ') }} +{%- endblock %} + +{% block page_title -%} + {% set episodeNumber = page.url|trim('/')|split('/')|last|split('-')|first -%} + + Episode {{ episodeNumber }}: {{ page.topic }} with {{ page.guests|join(' and ') }} +{%- endblock %} + +{% block head_title %} + {{ block('page_title') }} | Beyond Blocks podcast | {{ site.name }} + + +{% endblock %} + +{% block content_wrapper %} + {% if page.episode_filename %} + + {% endif %} + + {{ parent() }} + + {% if page.talking_points %} +
+

Key points

+ +
    + {% for point in page.talking_points %} +
  • {{ point }}
  • + {% endfor %} +
+
+ {% endif %} + + {% if page.quotes %} +
+

Quotes

+ +
    + {% for quote in page.quotes %} +
  • {{ quote }}
  • + {% endfor %} +
+
+ {% endif %} + +
+

Links

+ +
    + {% for link in page.links %} +
  • + {{ link.0 }} +
  • + {% endfor %} +
      +
+ + {% for guest in page.guests %} + {% include 'podcast/other-episodes.html.twig' with { + all_episodes: data.podcast_episodes, + guest, + topic: page.topic, + } only %} + {% endfor %} +{% endblock %} diff --git a/sculpin/source/_layouts/post.html.twig b/sculpin/source/_layouts/post.html.twig new file mode 100644 index 000000000..3f2b65ddd --- /dev/null +++ b/sculpin/source/_layouts/post.html.twig @@ -0,0 +1,11 @@ +{% extends 'page' %} + +{% block content_wrapper %} + + + {{ parent() }} +{% endblock %} + +{% block content_bottom %} + {% include 'about-me.html.twig' %} +{% endblock %} diff --git a/sculpin/source/_layouts/presentation.html.twig b/sculpin/source/_layouts/presentation.html.twig new file mode 100644 index 000000000..a0575e0dd --- /dev/null +++ b/sculpin/source/_layouts/presentation.html.twig @@ -0,0 +1,31 @@ +{% extends 'page' %} + +{% block meta_description %}{{ page.title }} presented by Oliver Davies{% endblock %} + +{% block content_wrapper %} + {{ parent() }} + + {% if block('abstract') %} +

Abstract

+ + {% block abstract %}{% endblock %} + {% endif %} + + {% if page.new_events %} + {% include 'presentation/events-new' with { + events: page.events, + } %} + {% else %} + {% include 'presentation/slides' with { + speakerdeck: page.speakerdeck, + } %} + + {% include 'presentation/video' with { + video: page.video, + } %} + + {% include 'presentation/events' with { + events: page.events, + } %} + {% endif %} +{% endblock %} diff --git a/sculpin/source/_pages/404.md b/sculpin/source/_pages/404.md new file mode 100644 index 000000000..84c8f7b0e --- /dev/null +++ b/sculpin/source/_pages/404.md @@ -0,0 +1,21 @@ +--- +layout: page +title: Page not found +--- + +{% block content %} +Perhaps you were looking for one of these pages: + +- [Products and services](/pricing) +- [Public speaking and workshops](/presentations) +- [My daily email list](/daily) +- [The Beyond Blocks podcast](/podcast) + +If you were looking for something else, you can [search for it](/search). +{% endblock %} + +{% block content_bottom %} + {% include 'daily-email-form.html.twig' with { + intro: 'Sign up and get daily emails about Drupal, PHP and software development.' + } %} +{% endblock %} diff --git a/sculpin/source/_pages/atdc-welcome.md b/sculpin/source/_pages/atdc-welcome.md new file mode 100644 index 000000000..67a19af84 --- /dev/null +++ b/sculpin/source/_pages/atdc-welcome.md @@ -0,0 +1,24 @@ +--- +layout: page +title: Welcome to the Test-Driven Drupal email course +meta: + title: Welcome to the Test-Driven Drupal email course | %site.name% +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Hi. Thank you for registering for my Test-Driven Drupal email course. + +Every email will be sent from my personal email address, so if you have a question about any email, press reply, send it to me, and I'll personally respond. + +I'd also appreciate any feedback as you work through or complete the course. + +Remember to check your inbox and confirm your email address to ensure you get the lessons. + +In the meantime, why not [go to my daily email archive](/archive) and read some of my previous daily emails? + +Found this page by accident? [Consider subscribing for the course](/atdc). +{% endblock %} diff --git a/sculpin/source/_pages/atdc.md b/sculpin/source/_pages/atdc.md new file mode 100644 index 000000000..77aa24660 --- /dev/null +++ b/sculpin/source/_pages/atdc.md @@ -0,0 +1,26 @@ +--- +layout: page +title: Automated Testing in Drupal email course +--- + +{% block content %} + +Do you want to learn how to write automated tests and do test-driven development in Drupal? + +Register below for my free 10-day email course, where you'll learn to write a new Drupal module from scratch with automated tests. + +Learn to test things like: + +* Whether pages exist. +* Whether users can view specific pages based on their permissions. +* Whether certain content is visible on a page given particular circumstances. +* Refactoring code to test dedicated classes such as Services, Repositories, Builders and Actions. + +{% include 'email-course-form.html.twig' %} +{% endblock %} + +{% block content_bottom %} +
+ {% include 'testimonials' with { tag: 'atdc' } %} +
+{% endblock %} diff --git a/sculpin/source/_pages/bcm.md b/sculpin/source/_pages/bcm.md new file mode 100644 index 000000000..2e09fd13c --- /dev/null +++ b/sculpin/source/_pages/bcm.md @@ -0,0 +1,30 @@ +--- +layout: page +title: Hi, PHP UserGroup Munich! +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Thanks for attending my talk on [Build Configs](/build-configs). + +[These are the slides](/talks/building-build-configs) I presented and the example video: + +{% include 'youtube-video' with { id: 'LkhsdmxReUc'} %} + +From nothing to a working Drupal 10 website in less than a minute! + +If you have any further questions, let me know. + +## Can we work together? + +[Get in touch](/contact) if you're interested in using Build Configs-based managed configuration files in your projects (I offer one-off implementations or ongoing updates via a subscription), you need an in-house tool built for your team, or if we can [work together another way](/pricing). + +## While you're here + +Why not join my [daily email list](/daily) or register for my [free email course](/atdc) on automated testing in Drupal? + +Oliver +{% endblock %} diff --git a/sculpin/source/_pages/bco.md b/sculpin/source/_pages/bco.md new file mode 100644 index 000000000..a47b33c70 --- /dev/null +++ b/sculpin/source/_pages/bco.md @@ -0,0 +1,32 @@ +--- +layout: page +title: Hi, PHP Oxford! +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Thanks for attending my talk on [Build Configs](/build-configs). + +[These are the slides](/presentations/building-build-configs) I presented and the example video: + +{% include 'youtube-video' with { id: 'LkhsdmxReUc'} %} + +From nothing to a working Drupal 10 website in less than a minute! + +If you have any further questions, let me know. + +## Can we work together? + +[Get in touch](/contact) if you're interested in using Build Configs-based managed configuration files in your projects (I offer one-off implementations or ongoing updates via a subscription), you need an in-house tool built for your team, or if we can [work together another way](/pricing). + +If you liked the talk, or [any of my others](/presentations), I can also present talks and run workshops for companies. + +## While you're here + +Why not join my [daily email list](/daily) or register for my [free email course](/atdc) on automated testing in Drupal? + +Oliver +{% endblock %} diff --git a/sculpin/source/_pages/blog.html.twig b/sculpin/source/_pages/blog.html.twig new file mode 100644 index 000000000..bcb51dc59 --- /dev/null +++ b/sculpin/source/_pages/blog.html.twig @@ -0,0 +1,27 @@ +--- +title: Blog +generator: pagination +pagination: + max_per_page: 30 + provider: data.posts +use: [posts] +--- + +{% if site.features.show_blog_post_count %} + {{ data.posts|length|number_format }} +{% endif %} + + diff --git a/sculpin/source/_pages/brumphp.md b/sculpin/source/_pages/brumphp.md new file mode 100644 index 000000000..1736a45d4 --- /dev/null +++ b/sculpin/source/_pages/brumphp.md @@ -0,0 +1,38 @@ +--- +layout: page +title: BrumPHP +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Thank you for attending my Sculpin talk at BrumPHP. + +[The slides and a previous recording](/talks/building-static-websites-sculpin) are on the talk page. + +To see an example of a Sculpin project, you can see [the source code for this website](https://github.com/opdavies/oliverdavies.uk) or [my demo for PHP South West](https://github.com/opdavies/phpsw-sculpin-demo). + +If you want to try Sculpin, you can use [the Sculpin Skeleton project I created](https://github.com/opdavies/sculpin-skeleton) as a starting point for new projects. + +## Can we work together? + +As well as building static websites with Sculpin, I do consulting and advisory work using other PHP projects - namely, Drupal and Symfony. + +I offer [unlimited monthly Drupal consulting](/consulting), [1-on-1 consultation calls](/call) and [pair programming sessions](/pair) to get people unstuck, and fixed prices (not estimates) for development work. + +## Are you stuck on Drupal 7, 8 or 9? + +Drupal 7 will be end-of-life and no longer supported as of the 5th of January, 2025. + +Drupal 8 and 9 are already unsupported. + +If you have an outdated Drupal website and want to know more about upgrading to Drupal 10, [book your upgrade roadmap](/drupal-upgrade) and I'll help you get there. + +## Stay in touch + +The best way to stay in touch with me is my [email list](/daily) to which I send daily emails about Drupal and software development. + +All emails are sent from my personal email address, so you can press reply and contact me directly. +{% endblock %} diff --git a/sculpin/source/_pages/build-configs.md b/sculpin/source/_pages/build-configs.md new file mode 100644 index 000000000..c00691186 --- /dev/null +++ b/sculpin/source/_pages/build-configs.md @@ -0,0 +1,78 @@ +--- +layout: page +title: "Build Configs - configuration files as a service" +products: + - + price: 2500 + link: https://buy.stripe.com/14kbJs98K1fc0p29AC + buttonText: Get started + - + price: 1000 + link: https://buy.stripe.com/7sIdRAbgS8HEfjWfZ1 + buttonText: Sign up +--- + +**Sprint zero in a box.** + +All of my projects contain similar build configuration files, such as Docker and Docker Compose files, PHPUnit and PHPStan configuration, and CI/CD pipeline workflows. I used to maintain these manually which was time-intensive and there was no guarantee that the same features or options were available from project to project. + +Build Configs is a tool I've written to maintain a canonical set of templates and generate them for each project based on a per-project configuration file. + +This makes it quicker and easier for me to create or onboard new projects to work on and, as all of the base files are centralised, when I fix something or add a new feature, the changes can be pushed to every project that uses it. + +I've been using this on personal projects such as my [Drupal](https://github.com/opdavies/docker-example-drupal), [LocalGov Drupal](https://github.com/opdavies/docker-example-drupal-localgov) and [Drupal Commerce Kickstart](https://github.com/opdavies/docker-example-drupal-commerce-kickstart) Docker examples and for various client projects. + +## How does it work? + +- I create a `build.yaml` file for the project that contains its configuration - what version of PHP it needs, which web server to use, which paths to run automated tests from or static analysis on, etc. +- I run the `build-configs` tool which generates the required files, such as a Dockerfile, Docker Compose file, PHPStan and PHPUnit configuration files, and a `run` script for automating project commands. +- The files are committed to version control and pushed to your code repository (GitHub, GitLab, Bitbucket, etc). +- As I add new features or make changes, I will re-run the process to re-generate the files and push any changes - ensuring you’re always up to date. + +## What are some of the recent new features? + +* Adding additional databases for working with migrations or multi-site projects. +* Adding additional `run` tasks. +* Adding CI pipelines with GitHub Actions to run automated quality checks. +* Creating and running Git hooks to run automated checks before changes are pushed. + +## Example + +In this short video, I show how Build Configs works by creating a new Drupal 10 project, generating its configuration files, and opening it in a browser. + +From nothing to a ready-to-work-on Drupal website in less than a minute. + +{% include 'youtube-video.html.twig' with { id: 'LkhsdmxReUc'} %} + +## Options + +### Initial project setup - £{{ page.products.0.price|number_format() }} + +To get your project started on the right foot, I will create a new Drupal project skeleton for you using `build-configs` that is ready to work on, including all of the generated files. You can even edit them if you like as they will get no ongoing updates. + +{% include 'button.html.twig' with { + text: page.products.0.buttonText, + url: page.products.0.link, +} %} + +### Ongoing updates and support (single site) - £{{ page.products.1.price|number_format }} per month + +Once you have a project with `build-configs`, if you want to receive ongoing updates to the generated files, I can automatically refresh your files once changes are available and push them to your code repository. + +This also includes unlimited support via a dedicated Slack channel and you can make feature requests for me to consider adding to the roadmap. + +If you like, I can add you to a beta users list and you’ll get new experimental features before anyone else. + +{% include 'button.html.twig' with { + text: page.products.1.buttonText, + url: page.products.1.link, +} %} + + +If you have multiple Drupal sites, [contact me](/contact) and we can work something out. + +### Retro-fitting into an existing project + +`build-configs` can also be added to an existing project. It can be tricky and will be different from project to project so [contact me](/contact) and we can discuss it further. + +Once I know more about your project, I’ll be happy to give you a fixed-price quote to do the work. diff --git a/sculpin/source/_pages/call.html.twig b/sculpin/source/_pages/call.html.twig new file mode 100644 index 000000000..9789c35d0 --- /dev/null +++ b/sculpin/source/_pages/call.html.twig @@ -0,0 +1,124 @@ +--- +layout: page +title: Book a 1-on-1 consulting call +link: https://savvycal.com/opdavies/consulting-call +price: 350 +faqs: + - + - What happens after I pay? + - Your call is scheduled at the time you pay. So after payment is received, we're all set! + - + - What if I can't find a suitable time? + - If you can't find a suitable time, due to your time zone, or weekly schedule, just send me an email, and we can arrange something. I try to be as flexible as possible! + - + - Can my colleague or business partner join the call? + - No. This is a 1-on-1 call. You are welcome to record the conversation to share it after the fact. + - + - Do you offer something more hands-on? + - Sure! Book a pair programming session instead and we’ll work on your code together. + - + - I still have questions! + - No problem. Send me an email at oliver@oliverdavies.uk. +--- + +{% block content %} + +{#

Who is this for?

#} + +{# Pain #} + +{# Dream #} + +{# Fix #} + +

As a professional Software Developer and Consultant with {{ get_years_of_experience() }} years of Drupal and PHP experience, I have a lot of knowledge that I use to help customers and their projects.

+ +{# 1st call to action #} + +{% include 'button' with { + position: 'centre', + text: 'Book your call now', + url: page.link, + withArrow: true, +} %} + +

Some things I can help you with

+ +
    +
  • How to approach a new project or task.
  • +
  • PHP and Drupal fundamentals and best practices.
  • +
  • Adding eCommerce functionality with Drupal Commerce.
  • +
  • Upgrading Drupal websites from unsupported versions.
  • +
  • Writing your first automated tests with PHPUnit or starting with test-driven development.
  • +
  • Introducing static analysis or other code quality tools to your project.
  • +
  • Adopting a utility-first CSS approach, e.g. Tailwind CSS, within a new or existing theme.
  • +
  • Configuring continuous integration (CI) pipelines with GitHub Actions, GitLab CI or Bitbucket Pipelines.
  • +
  • Automating tasks with Docker or Ansible.
  • +
  • Help fixing a bug or some broken code.
  • +
  • Reviewing your code and providing advice and suggestions.
  • +
+ +

In this 1-on-1 video call, I can help you answer questions in these areas or any others you may have.

+ +{% include 'button' with { + position: 'centre', + text: 'Book your call now', + url: page.link, + withArrow: true, +} %} + +{# Social proof #} + +{% include 'testimonials' with { tag: 'call' } %} + +{# Overcome objections #} + +

100% money-back guarantee!

+ +

If you don't find the call valuable, just let me know, and I'll refund 100% of the cost.

+ +

Frequently asked questions

+ +{% for faq in page.faqs %} +
  • +

    {{ faq.0 }}

    +

    {{ faq.1|raw }}

    +
  • +{% endfor %} + +{# Uniqueness #} + +

    Who am I?

    + +
      +
    • I'm an Acquia-certified Drupal expert with {{ get_years_of_experience() }} years of professional development experience.
    • +
    • I'm a former Drupal Association employee who was responsible for improving and maintaining Drupal.org.
    • +
    • I'm a Drupal core contributor and maintain numerous Drupal projects, including the Override Node Options module, which is used on over 38,000 websites.
    • +
    • I'm a multiple-time DrupalCon speaker who regularly presents talks and workshops at conferences and meetups.
    • +
    + +{# 2nd CTA #} + +{% embed 'callout.html.twig' with { + title: 'Ready to book your call?', +} %} + {% block callout_content %} + {% include 'button.html.twig' with { + text: 'Book your call now for £' ~ page.price|number_format ~ '', + url: page.link, + withArrow: true, + } %} + +

    You can pay and reserve your time slot straight away. There are a limited number of available slots each month. If, after the call, you decide to do a longer engagement with me, the cost of this call will be deducted from that engagement.

    + {% endblock %} +{% endembed %} + +{# Urgency #} + +

    Availability is limited

    + +

    I’m only available for a few 1-on-1 calls per month.

    + +

    Scheduling is first come, first served, so the sooner you book your time slot, the sooner you will have the answers you need to move your project forward.

    + +{% endblock %} diff --git a/sculpin/source/_pages/contact.md b/sculpin/source/_pages/contact.md new file mode 100644 index 000000000..adcb1f45d --- /dev/null +++ b/sculpin/source/_pages/contact.md @@ -0,0 +1,10 @@ +--- +layout: page +title: Contact Oliver +--- + +The best way to get in touch with me is via email. I usually reply within one business day. + +I'm also on [LinkedIn][linkedin]. + +[linkedin]: https://www.linkedin.com/in/opdavies diff --git a/sculpin/source/_pages/dcg.md b/sculpin/source/_pages/dcg.md new file mode 100644 index 000000000..74d3f8758 --- /dev/null +++ b/sculpin/source/_pages/dcg.md @@ -0,0 +1,36 @@ +--- +layout: page +title: DrupalCamp Ghent 2024 +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Thank you for attending my session at DrupalCamp Ghent. + +You can view the slides and previous recordings of my [Test Driven Drupal][] and [Tailwind CSS][] talks on this website. + +If you want to learn more, I released a video of the [Tailwind CSS workshop][workshop] I gave for DrupalCamp Florida, and I've created a [free 10-day email course][course] on automated testing in Drupal. + +## Can we work together? + +Automated testing, test-driven development and Tailwind CSS are some of my favourite subjects to teach. + +If you want me to teach your team to do test-driven development or build UIs with Tailwind CSS, team training is included within my [unlimited monthly Drupal consulting][consulting]. + +## Stay in touch + +The best way to stay in touch with me is my [email list] to which I send daily emails about Drupal and software development. + +All emails are sent from my personal email address, so you can press reply and contact me directly. + +[consulting]: /consulting +[course]: /atdc +[email list]: /daily +[tailwind css]: /presentations/taking-flight-with-tailwind-css +[test driven drupal]: /presentations/tdd-test-driven-drupal +[workshop]: /daily/2024/01/22/tailwind-css-workshop-recording + +{% endblock %} diff --git a/sculpin/source/_pages/drupal-london.md b/sculpin/source/_pages/drupal-london.md new file mode 100644 index 000000000..2870d5d86 --- /dev/null +++ b/sculpin/source/_pages/drupal-london.md @@ -0,0 +1,40 @@ +--- +layout: page +title: Drupal London +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Thank you for attending my session for the Drupal London meetup. + +You can [view the slides and previous recording][slides] of the talk on this website and [the example repository on GitHub][repo]. + +If you want to learn more, I released a [free 10-day email course][course] on automated testing in Drupal and [live stream on YouTube][youtube]. Most recently, [I contributed tests to the Content Access by Path module][video]. + +## Can we work together? + +Drupal, automated testing and test-driven development are some of my favourite subjects to teach. + +If you want me to teach your team to do test-driven development, team training is included within my [unlimited monthly Drupal consulting][consulting]. + +## Stay in touch + +The best way to stay in touch with me is my [email list] to which I send daily emails about Drupal and software development. + +All emails are sent from my personal email address, so you can press reply and contact me directly. + +I also host the [Beyond Blocks podcast][podcast] where I discuss Drupal, PHP and other software-related topics with people. + +[consulting]: /consulting +[course]: /atdc +[email list]: /daily +[podcast]: /podcast +[repo]: http://github.com/opdavies/drupal-london-meetup +[slides]: /presentations/tdd-test-driven-drupal +[video]: https://www.youtube.com/watch?v=XTpliKd47Lg +[youtube]: https://www.youtube.com/@opdavies + +{% endblock %} diff --git a/sculpin/source/_pages/drupal-upgrade.md b/sculpin/source/_pages/drupal-upgrade.md new file mode 100644 index 000000000..47279d3f4 --- /dev/null +++ b/sculpin/source/_pages/drupal-upgrade.md @@ -0,0 +1,86 @@ +--- +layout: page +title: Are you stuck on Drupal 7, 8 or 9? +button: + text: Book your roadmap now + url: https://buy.stripe.com/aEU4h0gBc4ro0p27sz +--- + +{# Pain #} + +Drupal 7 will be unsupported on the **5th of January 2025**. + +Drupal 8 has been unsupported since **November 2021**, and Drupal 9 since **November 2023**. + +Are you stuck on any of these versions? + +* Do you need to upgrade your website before it reaches its end-of-life date and is no longer supported? +* Are you worried about rebuilding your website and migrating your data to Drupal 10? +* Is all of your business logic embedded within your Drupal code, making it hard to upgrade? +* Do you rely on modules or themes that are no longer updated or don't exist for Drupal 10? + +{# Dream #} + +## What if you had a clear path how to upgrade your website? + +* What if you had a recommended approach to upgrade your website to Drupal 10? +* What if you knew about potential issues ahead of time? +* What if you had a list of modules to use in Drupal 10, alternatives for any missing modules, and what functionality would need custom code? + +{# Fix #} + +## Drupal upgrade roadmap + +An upgrade roadmap is a personalised audit of your Drupal website and includes details and actionable steps to upgrade it, including identifying potential blockers you might encounter. + +{# 1st call to action #} + +{% include 'button.html.twig' with { + text: page.button.text ~ ' ', + url: page.button.url, + withArrow: true, +} %} + +## How does it work? + +* After receiving payment, we will arrange an initial call to discuss your project. +* You share your source code and provide access to your website. + * I'll need access to the source code for your website. Ideally, this is via GitHub, GitLab, Bitbucket, or whatever online version control you currently use, but I can also audit a zip file of your Git repository. + * I'll need a user account to access your website to review its configuration, such as content types, user roles, etc. You can delete this once the engagement is complete. + * Alternatively, I can use an export of the database to get a local version of your site up and running. Ideally, this would be sanitised to remove personal information such as usernames, email addresses and passwords. +* I'll send you the document once it's complete for you to review. +* We'll arrange a follow-up call to go through it in detail and for you to ask any questions. + +{# 2nd CTA #} + +{% include 'button.html.twig' with { + text: page.button.text, + url: page.button.url, + withArrow: true, +} %} + +{# Social proof #} + +{% include 'testimonials.html.twig' %} + +{# Overcome objections #} + +{# Uniqueness #} + +## Who am I? + +* I'm an Acquia-certified Drupal expert with {{ get_years_of_experience() }} years of professional development experience. +* I'm a former Drupal Association employee who was responsible for improving and maintaining Drupal.org. +* I'm a Drupal core contributor and maintain numerous Drupal projects, including the Override Node Options module, which is used on over 38,000 websites. +* I'm a multiple-time DrupalCon speaker who regularly presents talks and workshops at conferences and meetups. + +{# Urgency #} + +## Availability is limited + +There will be no further extensions of Drupal 7 support, and I have limited availability due to the time required, so buy now to secure your place. + +{% include 'button.html.twig' with { + text: page.button.text ~ ' →', + url: page.button.url, +} %} diff --git a/sculpin/source/_pages/drupalcamp-ghent.md b/sculpin/source/_pages/drupalcamp-ghent.md new file mode 100644 index 000000000..907b0518f --- /dev/null +++ b/sculpin/source/_pages/drupalcamp-ghent.md @@ -0,0 +1,28 @@ +--- +layout: page +title: DrupalCamp Ghent 2024 +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Thank you for attending my session at DrupalCamp Ghent. + +You can view the slides and previous recordings of my [Test Driven Drupal](/talks/tdd-test-driven-drupal) and [Tailwind CSS](/talks/taking-flight-with-tailwind-css) talks on this website. + +If you want to learn more, I released a video of the [Tailwind CSS workshop](/daily/2024/01/22/tailwind-css-workshop-recording) I gave for DrupalCamp Florida, and I've created a [free 10-day email course](/atdc) on automated testing in Drupal. + +## Can we work together? + +Automated testing, test-driven development and Tailwind CSS are some of my favourite subjects to teach. + +If you want me to teach your team to do test-driven development or build UIs with Tailwind CSS, team training is included in my [unlimited monthly Drupal consulting](/consulting). + +## Stay in touch + +The best way to stay in touch with me is my [email list](/daily) to which I send daily emails about Drupal and software development. + +All emails are sent from my personal email address, so you can press reply and contact me directly. +{% endblock %} diff --git a/sculpin/source/_pages/drupalgive.md b/sculpin/source/_pages/drupalgive.md new file mode 100644 index 000000000..e4a7efe0c --- /dev/null +++ b/sculpin/source/_pages/drupalgive.md @@ -0,0 +1,89 @@ +--- +layout: page +title: My Drupal Contributions +modules: + - + name: Block ARIA Landmark Roles + machine_name: block_aria_landmark_roles + type: module + usage: 1346 + stars: 16 + - + name: Copyright Block + machine_name: copyright_block + type: module + usage: 2514 + stars: 10 + - + name: Feature Toggle Twig + machine_name: feature_toggle_twig + type: module + - + name: Layout Builder Extra Templates + machine_name: override_node_options + type: module + usage: 325 + stars: 11 + - + name: Null User + machine_name: null_user + type: module + usage: 5 + stars: 4 + - + name: System User + machine_name: system_user + type: module + - + name: Tailwind CSS Starter Kit + machine_name: tailwindcss + type: theme + usage: 260 +--- + +[This is my profile page on Drupal.org](https://www.drupal.org/u/opdavies) and these are some of the projects I maintain: + +
      + {% for project in page.modules|sort((a, b) => b.usage <=> a.usage) %} +
    • + {{ project.type|capitalize }}: + {{ project.name }} + {% if project.usage %} + - {{ project.usage|number_format }} websites + {%- if project.stars -%} + , {{ project.stars }} {{ project.stars == 1 ? 'star' : 'stars' }} + {% endif %} + {% endif %} +
    • + {% endfor %} +
    + +## Example Projects on GitHub + +- [Docker Example Drupal](https://github.com/opdavies/docker-example-drupal) +- [Docker Example Drupal Commerce Kickstart](https://github.com/opdavies/docker-example-drupal-commerce-kickstart) +- [Docker Example Drupal LocalGov](https://github.com/opdavies/docker-example-drupal-localgov) + +## Events + +- I was a speaker at DrupalCon Lille in October 2023. +- I was a speaker at DrupalCon Europe 2020 (online). +- I was a workshop trainer at DrupalCamp NYC 2020 (online). +- I was a workshop trainer at DrupalCamp London 2020 (online). +- I was a speaker at DrupalCon Amsterdam in October 2019. +- I was a contribution day mentor at DrupalCon Vienna 2017. +- I was a speaker at DrupalCamp Dublin 2017. +- I was a speaker at DrupalCamp Bristol 2016. +- I was an organiser of DrupalCamp Bristol (2016, 2017, 2019). +- I was a contribution day mentor at DrupalCon Los Angeles and Barcelona 2015. +- I was a speaker at DrupalCamp North 2015. +- I was a speaker at DrupalCamp Brighton 2015. +- I was a contribution day mentor at DrupalCon Amsterdam 2014. +- I was a speaker at DrupalCamp London (2014, 2015, 2016, 2017, 2019). +- I was a volunteer at DrupalCamp London 2014. +- I was a contribution day mentor at DrupalCon Prague 2013. +- I was an organiser of the South Wales Drupal user group (SWDUG) and Drupal Bristol user group. + +## Other + +- I'm a Board Member of the [Drupal England and Wales Association](https://drupal-england-wales.github.io) (DEW). diff --git a/sculpin/source/_pages/dto.md b/sculpin/source/_pages/dto.md new file mode 100644 index 000000000..9eb03feff --- /dev/null +++ b/sculpin/source/_pages/dto.md @@ -0,0 +1,46 @@ +--- +layout: page +title: Introduction to Automated Testing and Test-Driven Development with Drupal +drupal_version: 10 +prices: + early: 299 + full: 499 +is_early_bird: true +next_date: 2024-02-23 +--- + +Are you a Drupal Developer who wants to learn about automated testing and test-driven development, or do you manage a development team that you'd like to train? + +I've delivered large Drupal projects using automated tests and test-driven development for custom functionality, and maintain Drupal modules with thousands of installations whilst using their tests to ensure working code and prevent regressions. + +I offer an interactive full-day workshop (previously presented at DrupalCamp London, and remotely for DrupalCamp NYC) that provides an introduction to automated testing in Drupal and how to utilise test-driven development - which I've updated specifically for Drupal {{ page.drupal_version }}. + +## Contents + +- What is automated testing, and why write tests? +- What types of tests are available in Drupal? +- Outside-in vs. inside-out testing. +- Configuring Drupal and PHPUnit to run tests locally. +- Exercise: writing tests for existing Drupal core functionality. +- Exercise: adding tests to an existing custom module. +- What is test-driven development? +- Exercise: writing a new Drupal module from scratch with test-driven development. +- Q&A + +
    + +## Dates and prices + +The workshop is currently only available remotely, and the next available date is {{ page.next_date|date('F jS, Y') }}. + +Seats are available at {{ page.is_early_bird ? 'an early bird price of £' ~ page.prices.early : 'a price of £' ~ page.prices.full }}, with a 10% discount for bulk orders of 5 or more seats. + +{% include 'button.html.twig' with { + text: 'Book your seat', + url: 'https://buy.stripe.com/aEU9Bk2KmaPM3Be8wJ', + withArrow: true, +} %} + +
    + +{% include 'testimonials' with { tag: 'testing' } %} diff --git a/sculpin/source/_pages/glossary.html.twig b/sculpin/source/_pages/glossary.html.twig new file mode 100644 index 000000000..4481d0370 --- /dev/null +++ b/sculpin/source/_pages/glossary.html.twig @@ -0,0 +1,35 @@ +--- +layout: page +title: Glossary +terms: + - + - Automated Testing + - + - CI pipeline + - + - Continuous integration + - | + The process of continuously integrating your code with other people's code, i.e. at least once a day. + This is done by regularly pulling and merging everyone else's code with yours and pushing yours so it's available for others to do the same. This can also refer to CI pipelines and tools like GitHub Actions and GitLab CI. + - + - Continuous Delivery and Deployment + - + - Git + - + - PHPStan + - + - Static analysis + - + - Test-Driven Development + - + - Trunk-based Development + - + - Version control +--- + +
    + {% for term in page.terms if term.1 %} +
    {{ term.0 }}
    +
    {{ term.1 }}
    + {% endfor %} +
    diff --git a/sculpin/source/_pages/homelab.md b/sculpin/source/_pages/homelab.md new file mode 100644 index 000000000..21e6baaf4 --- /dev/null +++ b/sculpin/source/_pages/homelab.md @@ -0,0 +1,24 @@ +--- +title: Homelab +--- + +My homelab/home server is running on a TUXEDO InfinityBook Pro Gen7 laptop and uses [NixOS as the operating system][0]. + +It hosts this website and a number of other static websites. + +I also use it to self-host these services: + +- [Audio Bookshelf](https://www.audiobookshelf.org) +- [Forgejo](https://forgejo.org) +- [Home Assistant](https://www.home-assistant.io) +- [Homepage](https://gethomepage.dev) +- [Immich](https://immich.app) +- [Jellyfin](https://jellyfin.org) +- [Mastodon](https://joinmastodon.org) (work in progress) +- [Paperless-ngx](https://docs.paperless-ngx.com) +- [Peertube](https://peertube.tv) +- [Tube Archivist](https://www.tubearchivist.com) +- [Uptime Kuma](https://uptime.kuma.pet) +- [Vaultwarden](https://github.com/dani-garcia/vaultwarden) + +[0]: {{site.code.url}}/{{site.code.username}}/nix-config diff --git a/sculpin/source/_pages/index.html.twig b/sculpin/source/_pages/index.html.twig new file mode 100644 index 000000000..df78f0170 --- /dev/null +++ b/sculpin/source/_pages/index.html.twig @@ -0,0 +1,101 @@ +--- +layout: page +permalink: / +title: Oliver Davies - Drupal Developer, Consultant and Speaker +meta: + title: Drupal Development and Consulting by Oliver Davies +urls: + exploratory_call: https://savvycal.com/opdavies/drupal-consulting-exploratory-call +--- + +{% block content %} + +{# Pain #} + +
      +
    • Are bugs and errors on your Drupal website losing you customers?
    • +
    • Are you stuck on an outdated or unsupported version of Drupal?
    • +
    • Are you unable to efficiently change your website and spend your time searching for workarounds?
    • +
    • Does it take too long to release new features and bug fixes?
    • +
    • Are you considering switching to Drupal from your current CMS and wondering if it's the right choice?
    • +
    + + + +
    + +{# Solution #} + +

    What can I do for you?

    + +{# TODO: add more information about each of these. #} + +
      +
    • Analysis & Audit. I can help you identify expensive bottlenecks, hidden issues, and potential problems with your site. I'll put together a detailed report with actionable next-steps on how to fix any issues.
    • +
    • Roadmap & Planning. We'll identify your goals and challenges, and I'll put together a custom roadmap to help you get there.
    • +
    • Implementation and Maintenance. I can build your project for you, or work with your engineering team to accelerate your progress.
    • +
    • Team Training. Give your team the skills they need to get more done. Grow, retain, and attract talented developers.
    • +
    • Ongoing Advisory. Throughout the duration of your project, I'll be available to review progress, answer questions, recommend tools and processes, share emerging best practices, and keep your project on the right track.
    • +
    + +
    + +

    You're already running my code in production

    + +

    I've contributed code to Drupal core and written popular contributed Drupal modules and themes, PHP and JavaScript libraries, and Tailwind CSS plugins.

    + +

    For example, the Override Node Options module is used on around 40,000 active Drupal websites.

    + +
    + +

    Here's some of my recent work

    + +
      +
    • I developed a Drupal module to integrate with a third-party translation provider, enabling automated translations of English-only content from XML feeds into different languages.
    • +
    • I created an example eCommerce application using Drupal Commerce for an asset finance company for their presentation to a multinational eCommerce company.
    • +
    • I migrated a membership portal for a UK health association from Drupal 7 to Drupal 10, migrating their content and users and rebuilding the required custom functionality.
    • +
    • I presented workshops on automated testing and test-driven development at Drupal conferences.
    • +
    • I assisted a UK consultancy in hiring their in-house Senior Drupal Developer by providing technical input for interviews and candidate feedback.
    • +
    • I developed a Tailwind CSS-based theme for a multi-tenant Drupal application, delivering the theme scaffolding, build system, and initial components. I also trained and supported the in-house development team.
    • +
    • I developed a Drupal Commerce application for an annual international photography competition that allows photographers to pay and submit their entries, including custom scoring functionality for jurors.
    • +
    + +
    + +

    Get in touch

    + +

    Unlike working with large agencies, you'll only work directly with me. You won't be handed off sub-contractors, offshore teams or Junior Developers who are learning on the job.

    + +

    I only give fixed prices so you'll know upfront how much my work will cost and all of my work is covered by a bug-free guarantee.

    + + +{% include 'button.html.twig' with { + full_width: true, + text: 'Click here to email Oliver', + url: 'mailto:' ~ site.email, +} %} + +
    + +{% include 'testimonials' with { + limit: 5, + tag: 'front', + title: 'Kind words from clients and customers', +} %} + +
    + +

    Get in touch

    + +

    There’s no reason to wait. Drop me a line and I'll get back to you ASAP.

    + +{% include 'button.html.twig' with { + full_width: true, + text: 'Click here to email Oliver', + url: 'mailto:' ~ site.email, +} %} +{% endblock %} diff --git a/sculpin/source/_pages/mob.md b/sculpin/source/_pages/mob.md new file mode 100644 index 000000000..b21f34369 --- /dev/null +++ b/sculpin/source/_pages/mob.md @@ -0,0 +1,16 @@ +--- +layout: page +title: An Introduction to Mob Programming +--- + +* +* +* +* +* + +
    + {% include 'youtube-video' with { id: '28S4CVkYhWA' } %} + {% include 'youtube-video' with { id: 'ri-35oHWIU8' } %} + {% include 'youtube-video' with { id: 'jPLEbZLE3g8' } %} +
    diff --git a/sculpin/source/_pages/pair.html.twig b/sculpin/source/_pages/pair.html.twig new file mode 100644 index 000000000..71d865329 --- /dev/null +++ b/sculpin/source/_pages/pair.html.twig @@ -0,0 +1,81 @@ +--- +layout: page +title: Pair program with me +price: 499 +link: https://savvycal.com/opdavies/pair +--- + +{% block content %} + +{# Pain #} + +

    Are you stuck adding a new feature or fixing a bug?

    + +

    Do you need help starting a new Drupal module or theme?

    + +

    Would you like another pair of eyes on your code, providing real-time suggestions and feedback rather than waiting for a code review?

    + +{# Dream #} + +{# Fix #} + +

    Book a pair programming session

    + +

    What if you could have a pair programming session with a Lead Developer and Drupal Expert with {numberOfYears} years of professional experience?

    + +

    Book a 2-hour pair programming call, and we can work on your code together - adding new functionality, fixing bugs, writing tests for existing code, or something else.

    + +

    Price: £{{ page.price|number_format }}

    + +{# 1st call to action #} + +{% include 'button.html.twig' with { + text: 'Book your session now', + url: page.link, +} %} + +{# Social proof #} + +{% include 'testimonials.html.twig' %} + +{# Overcome objections #} + +

    100% money-back guarantee!

    + +

    If you don't find the session valuable, just let me know, and I'll refund 100% of the cost.

    + +{# Uniqueness #} + +

    Who am I?

    + +
      +
    • I'm an Acquia-certified Drupal expert with {{ get_years_of_experience() }} years of professional development experience.
    • +
    • I'm a former Drupal Association employee who was responsible for improving and maintaining Drupal.org.
    • +
    • I'm a Drupal core contributor and maintain numerous Drupal projects, including the Override Node Options module, which is used on over 38,000 websites.
    • +
    • I'm a multiple-time DrupalCon speaker who regularly presents talks and workshops at conferences and meetups.
    • +
    + +{# 2nd CTA #} + +{% embed 'callout.html.twig' with { + title: 'Ready to book your session?', +} %} + {% block callout_content %} + {% include 'button.html.twig' with { + text: 'Book your session now for £' ~ page.price|number_format ~ ' ', + url: page.link, + withArrow: true, + } %} + +

    You can pay and reserve your time slot straight away. There are a limited number of available slots each month. If, after the call, you decide to do a longer engagement with me, the cost of this call will be deducted from that engagement.

    + {% endblock %} +{% endembed %} + +{# Urgency #} + +

    Availability is limited

    + +

    I’m only available for a few pair programming sessions per month.

    +

    Scheduling is first come, first served, so the sooner you book your time slot, the sooner you will have the answers you need to move your project forward.

    + +{% endblock %} diff --git a/sculpin/source/_pages/phpberks.md b/sculpin/source/_pages/phpberks.md new file mode 100644 index 000000000..3c7ae78b2 --- /dev/null +++ b/sculpin/source/_pages/phpberks.md @@ -0,0 +1,38 @@ +--- +layout: page +title: PHP Berkshire +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Thank you for attending my Sculpin talk at PHP Berkshire. + +[The slides and a previous recording](/presentations/building-static-websites-sculpin) are on the talk page. + +To see an example of a Sculpin project, you can see [the source code for this website](https://github.com/opdavies/oliverdavies.uk), [my Zettlekasten](https://github.com/opdavies/zet.oliverdavies.uk) or [my demo for PHP South West](https://github.com/opdavies/phpsw-sculpin-demo). + +If you want to try Sculpin, you can use [the Sculpin Skeleton project I created](https://github.com/opdavies/sculpin-skeleton) as a starting point for new projects. + +## Can we work together? + +As well as building static websites with Sculpin, I do consulting and advisory work using other PHP projects - namely, Drupal and Symfony. + +I offer [unlimited monthly Drupal consulting](/consulting), [1-on-1 consultation calls](/call) and [pair programming sessions](/pair) to get people unstuck, and fixed prices (not estimates) for development work. + +## Are you stuck on Drupal 7, 8 or 9? + +Drupal 7 will be end-of-life and no longer supported as of the 5th of January, 2025. + +Drupal 8 and 9 are already unsupported. + +If you have an outdated Drupal website and want to know more about upgrading to Drupal 10, [book your upgrade roadmap](/drupal-upgrade) and I'll help you get there. + +## Stay in touch + +The best way to stay in touch with me is my [email list](/daily) to which I send daily emails about Drupal and software development. + +All emails are sent from my personal email address, so you can press reply and contact me directly. +{% endblock %} diff --git a/sculpin/source/_pages/podcast.md b/sculpin/source/_pages/podcast.md new file mode 100644 index 000000000..766f46eaa --- /dev/null +++ b/sculpin/source/_pages/podcast.md @@ -0,0 +1,32 @@ +--- +layout: page +title: The Beyond Blocks podcast +meta: + description: A podcast about Drupal, PHP open-source and software development. +use: + - podcast_episodes +--- + +{% block content_bottom %}{% endblock %} + +{% block content %} +A podcast about Drupal, PHP, open-source, and related software development topics. +Guests include people like [Matt Glaman](/podcast/1-retrofit), [Eirik Morland](/podcast/8-eirik-morland-violinist), [Tim Lehnen](/podcast/9-tim-lehnen), [Ryan Szrama](/podcast/13-ryan-szrama-centarro), [Sam Mortenson](/podcast/19-sam-mortenson) and [Jess Archer](/podcast/25-jess-archer-drush-laravel-prompts). + +## Episodes {.sr-only} + +{% for episode in data.podcast_episodes|reverse %} + {% set episodeNumber = episode.url|trim('/')|split('/')|last|split('-')|first %} + +

    Episode {{ episodeNumber }}: {{ episode.topic }} with {{ episode.guests|join(' and ') }}

    + + + + {{ episode.blocks.content|markdown }} + + + Listen now + → + +{% endfor %} +{% endblock %} diff --git a/sculpin/source/_pages/presentations.html.twig b/sculpin/source/_pages/presentations.html.twig new file mode 100644 index 000000000..cdf39aafc --- /dev/null +++ b/sculpin/source/_pages/presentations.html.twig @@ -0,0 +1,23 @@ +--- +layout: page +title: Presentations +use: [presentations] +--- + +

    Since September 2012, I have given {{ get_presentation_count(data.presentations) }} public talks and workshops at various conferences and meetups, in-person and remotely, on topics including PHP, Drupal, automated testing, Git, CSS, and systems administration.

    + +{% for presentation in data.presentations|sort((a, b) => a.events|last.date|date('U') > b.events|last.date|date('U') ? -1 : 1) %} +
    + + + {% if presentation.blocks.description %} + {{ presentation.blocks.description|raw }} + {% else %} +

    {{ presentation.description }}

    + {% endif %} +
    +{% endfor %} diff --git a/sculpin/source/_pages/press.md b/sculpin/source/_pages/press.md new file mode 100644 index 000000000..b0a2f3a6a --- /dev/null +++ b/sculpin/source/_pages/press.md @@ -0,0 +1,43 @@ +--- +layout: page +title: Press Info +--- + +The following information is provided as a cut-and-paste resource for conference organisers, media professionals, podcast hosts, and other interested parties. + +Please feel free to use anything here as-is without checking with me first. If you have additional questions, you can email me directly. + +## Short Bio + +Oliver is a Software Developer and Drupal expert with {{ get_years_of_experience() }} years experience. He specialises in code quality, automated testing and test-driven development. + +## Sample Topics + +* Getting started in software development, Drupal, or open-source software. +* Building your first Drupal website. +* Drupal module and theme development. +* Automated testing and test-driven development (TDD). +* Static analysis in PHP applications. +* Utility-first styling and Tailwind CSS. +* Git and different ways to use it (continuous integration, trunk-based development). +* Contributing to open-source software. + +## Social Media and Elsewhere + +* [Drupal.org][drupal] +* [GitHub][] +* [LinkedIn][] +* [Twitter][] + +## Physical Location + +[Caerleon, Wales](https://www.google.co.uk/maps/place/Caerleon,+Newport) + +## Photo + +![](/assets/images/social-avatar.jpg) + +[drupal]: https://www.drupal.org/u/opdavies +[github]: https://github.com/opdavies +[linkedin]: https://www.linkedin.com/in/opdavies +[twitter]: https://twitter.com/opdavies diff --git a/sculpin/source/_pages/pricing.md b/sculpin/source/_pages/pricing.md new file mode 100644 index 000000000..6496cbe0f --- /dev/null +++ b/sculpin/source/_pages/pricing.md @@ -0,0 +1,114 @@ +--- +layout: page +title: Products and Services +products: + - + title: Drupal development subscription + description: | + In less time than it takes to post on a job board, and for a fraction of the cost, get unlimited access to a certified Drupal development expert, core contributor and multiple-time DrupalCon speaker for a fixed monthly fee. No surprises. Cancel anytime. + perMonth: true + price: 5000 + isFrom: true + link: + text: Register now + url: /subscription + - + title: Drupal upgrade roadmap + description: | + Are you stuck on an already or soon-to-be unsupported version of Drupal? Get a personalised roadmap of your Drupal website, including details and actionable steps to upgrade it. + price: 5000 + link: + text: Book your roadmap now + url: /drupal-upgrade + - + title: Diagnosis + description: | + An in-depth investigation into a single issue where I'll provide a report with my findings and advice on the next steps. Once you've purchased, you can book a Zoom call with me to discuss what you want me to investigate. + price: 2500 + link: + text: Book now + url: https://buy.stripe.com/00gbJs84G2jg8Vy9AJ + - + title: Private talk or workshop + description: | + If you found one of my public speaking presentations or workshops useful, I'm available for private speaking engagements on a variety of topics to help your team succeed. + price: 2000 + isFrom: true + link: + text: Schedule a talk + url: https://buy.stripe.com/eVa4h0bgSaPM6NqcMU + - + title: 1-on-1 consulting call + description: | + Book a 1-on-1 video call, and I can help you by answering questions about software development, architecture and automation, helping you write your first automated test, or reviewing some of your code and giving advice and suggestions. + price: 350 + link: + text: Book your call now + url: /call + - + title: Pair program with me + description: | + Would you like another pair of eyes on your code, providing real-time suggestions and feedback rather than waiting for a code review? Book a 2-hour pair programming call and we can work on your code together. + price: 499 + link: + text: Book your session now + url: /pair + - + title: Introduction to Automated Testing in Drupal - 10-day email course + description: | + Register for my free email course on automated testing in Drupal. + link: + text: Register now + url: /atdc + - + title: Drupal module template + description: | + If you're creating a new Drupal module, try starting with my free module template for Drupal 9 and 10. + link: + text: Download + url: https://github.com/opdavies/drupal-module-template +--- + +{% block content %} + +{% for product in page.products %} + +
    +

    + {{ product.title }} - + {{ product.isFrom ? 'from' }} + {% if product.price %} + £{{ product.price|number_format() }} + {% else %} + free! + {% endif %} + {{ product.perMonth ? 'per month' }} +

    + +
    +

    + {{ product.description }} + + {% if product.remainingPlaces == 1 %} + 1 place remaining! + {% elseif product.remainingPlaces > 1 %} + {{ product.remainingPlaces }} places remaining! + {% elseif product.isLimited %} + Limited places available! + {% endif %} +

    +
    + + +
    +{% endfor %} +{% endblock %} + +{% block content_top %} + {% include 'message.html.twig' %} +{% endblock %} diff --git a/sculpin/source/_pages/search.html.twig b/sculpin/source/_pages/search.html.twig new file mode 100644 index 000000000..42fe77e0f --- /dev/null +++ b/sculpin/source/_pages/search.html.twig @@ -0,0 +1,49 @@ +--- +layout: page +title: Search +common_searches: + - Drupal + - Test-Driven Development + - Automated testing + - Refactoring + - PHP + - Tailwind CSS + - Neovim + - Git + - Linux +--- + +
    +
    +
    + + +
    + +
    + +
    +
    +
    + + diff --git a/sculpin/source/_pages/sfs.md b/sculpin/source/_pages/sfs.md new file mode 100644 index 000000000..b01d87456 --- /dev/null +++ b/sculpin/source/_pages/sfs.md @@ -0,0 +1,10 @@ +--- +layout: page +title: Sculpin from Scratch +--- + +Coming soon: a daily email course on building static websites with Sculpin. + +If you're interested, why not [watch my Sculpin talk](/presentations/building-static-websites-sculpin) in the meantime or check out [the source code for this website](https://github.com/opdavies/oliverdavies.uk)? + +If you want me to let you know once the course is ready, send me an email and I'll add you to the list. diff --git a/sculpin/source/_pages/sitemap.xml.twig b/sculpin/source/_pages/sitemap.xml.twig new file mode 100644 index 000000000..7d493cd54 --- /dev/null +++ b/sculpin/source/_pages/sitemap.xml.twig @@ -0,0 +1,22 @@ +--- +permalink: /sitemap.xml +use: + - pages + - podcast_episodes + - posts + - presentations +default_priorities: + posts: '0.2' +--- + + + + {% for content_type, content in data %} + {% for item in content %} + + {{ site.url }}{{ item.url|trim('/', 'right') }} + {{ page.default_priorities[content_type]|default('0.5') }} + + {% endfor %} + {% endfor %} + diff --git a/sculpin/source/_pages/speaker.md b/sculpin/source/_pages/speaker.md new file mode 100644 index 000000000..309ac4b3a --- /dev/null +++ b/sculpin/source/_pages/speaker.md @@ -0,0 +1,32 @@ +--- +layout: page +title: Speaker Information +--- + +## Bio + +Oliver is a Software Developer and Drupal Expert with {{ get_years_of_experience() }} years of experience. As well as consulting on large Drupal projects, Oliver helps Drupal Developers learn automated testing and test-driven development via a free email course and paid coaching and workshops. He regularly contributes to open-source software projects, including Drupal core. + +## Photos + +- + +## Some events that I've spoken at + +- BlueConf 2019 (Cardiff, UK) +- DrupalCamp Brighton 2015 +- DrupalCamp Bristol 2016 +- DrupalCamp Dublin 2017 +- DrupalCamp London (2014, 2015, 2016, 2017, 2019, 2020) +- DrupalCamp North 2015 (Sunderland, UK) +- DrupalCon Amsterdam 2019 +- DrupalCon Europe 2020 (Online) +- DrupalCon Lille 2023 +- Nomad PHP +- Norfolk Developers' Conference (nor(DEV):con) 2023 +- PHP North West 2017 (Manchester, UK - 10 year anniversary) +- PHP South Coast 2016 (Portsmouth, UK) +- PHP UK Conference 2018 (London, UK) +- WordCamp Bristol 2019 + +I also [gave a number of talks remotely](/blog/speaking-remotely-during-lockdown) for various user groups and conferences during COVID-19. diff --git a/sculpin/source/_pages/sponsor.md b/sculpin/source/_pages/sponsor.md new file mode 100644 index 000000000..58f5d2b8d --- /dev/null +++ b/sculpin/source/_pages/sponsor.md @@ -0,0 +1,31 @@ +--- +layout: page +title: Sponsor me to work on Open Source Software +--- + +I enjoy working with and on open source software. + +I've been using PHP since 2007 and Drupal since 2008 and am an enthusiastic open source contributor. + +Drupal core, Drupal.org, LocalGov Drupal and Drupal Commerce are some of the projects I've contributed to. + +I maintain the popular Override Node Options module which is used on around 40,000 active Drupal websites and created a starterkit Drupal theme for Tailwind CSS. + +There are lots of other examples on my [Drupal.org][0] and [GitHub][1] profiles. + +I've found that companies want to contribute more, but are too busy. + +Most projects have a custom module or library that was going to be contributed back, but it just hasn't happened yet. + +## Why not sponsor a contributor? + +If you don't have time to contribute, why not sponsor me to do it for you? + +Whether it's contributing that module or library, adding a missing feature or fixing a bug in something you use, or you just want to sponsor me to work on open source, I'd love to hear from you. + +We can discuss how much time you want to sponsor and what you want me to focus on and I'll get to work. + +You'll be mentioned on any relevant blog posts, live streams, issues and pull or merge requests, so everyone will know that you sponsored me and you'll get the kudos. + +[0]: {{site.drupalorg.url}} +[1]: {{site.github.url}} diff --git a/sculpin/source/_pages/testimonials.md b/sculpin/source/_pages/testimonials.md new file mode 100644 index 000000000..32a72c8b6 --- /dev/null +++ b/sculpin/source/_pages/testimonials.md @@ -0,0 +1,9 @@ +--- +layout: page +title: Testimonials +--- + +{% include 'testimonials' with { + limit: 0, + title: 'All Testimonials', +} %} diff --git a/sculpin/source/_pages/things-about-php.md b/sculpin/source/_pages/things-about-php.md new file mode 100644 index 000000000..6f3cb0a90 --- /dev/null +++ b/sculpin/source/_pages/things-about-php.md @@ -0,0 +1,64 @@ +--- +layout: page +title: Things you should know about PHP +--- + +Thanks for attending my [Things you should know about PHP](/talks/things-you-should-know-about-php) talk. + +I hope that you learned some things about PHP, its ecosystem, and its communities, and if you haven't tried using PHP yet, I'd encourage you to do so. + +Here are links to the resources that I mention in the talk, plus a couple of extras. + +## Resources + +- [The PHP Foundation](https://thephp.foundation) - non-profit to support, advance, and develop the PHP language +- [PHP-FIG](https://www.php-fig.org) - PHP Framework Interop Group +- [Composer](https://getcomposer.org) - dependency manager +- [Drupal](https://www.drupal.org) - content management system +- [Jigsaw](https://jigsaw.tighten.co) - static site generator +- [Laravel](https://laravel.com) - framework +- [Nomad PHP](https://nomadphp.com) - online user group +- [PHP official images on Docker Hub](https://hub.docker.com/_/php) +- [PHPStan](https://phpstan.org) - static analysis tool +- [PHPUnit](https://phpunit.de) - testing framework +- [Pest](https://pestphp.com) - testing framework +- [Psalm](https://psalm.dev) - static analysis tool +- [Sculpin](khttps://sculpin.io) - static site generator +- [WordPress](https://wordpress.org) - content management system +- [php.net](https://www.php.net) - online documentation +- [php[architect]](https://www.phparch.com) - online magazine + +## Books + +- [Laravel: Up & Running](https://www.oreilly.com/library/view/laravel-up/9781492041207) +- [Symfony: The Fast Track](https://symfony.com/book) + +## Videos + +- [Codecourse](https://codecourse.com) +- [How to Code Well](https://www.howtocodewell.net) +- [Laracasts](https://laracasts.com) +- [SymfonyCasts](https://symfonycasts.com) + +## Podcasts + +- [How to Code Well podcast](https://howtocodewell.fm) +- [PHPUgly](https://www.phpugly.com) +- [Talking Drupal](https://talkingdrupal.com) +- [The Laravel Podcast](https://laravelpodcast.com) +- [The PHP Roundtable](https://phproundtable.com) +- [Voices of the elePHPant](https://voicesoftheelephpant.com) + +## Can I help? + +Do you want to introduce PHP to your company or team, or add one of these tools to your existing PHP application? + +I offer consulting calls and services to reduce your onboarding time and get you up and running quicker and easier. + +
    + {% include 'button.html.twig' with { + text: 'Book your call ', + url: '/call', + withArrow: true, + } %} +
    diff --git a/sculpin/source/_pages/welcome.md b/sculpin/source/_pages/welcome.md new file mode 100644 index 000000000..6a4ece758 --- /dev/null +++ b/sculpin/source/_pages/welcome.md @@ -0,0 +1,26 @@ +--- +layout: page +title: Welcome! +meta: + title: Welcome to my Daily Email list | %site.name% +--- + +{% block head_meta %} + +{% endblock %} + +{% block content %} +Hi. Thank you for subscribing to my Daily Email list! + +You'll soon start to get emails from me directly in your inbox. Every day. + +The first might be later today! + +Every email is sent from my personal email address, so if you have a question about any email, press reply, send it to me, and I'll personally respond. + +Also, remember to check your inbox and confirm your email address to ensure you get my emails. + +In the meantime, why not [go to the archive](/archive) and read some of my previous dailies? + +Found this page by accident? [Consider joining the list](/daily). +{% endblock %} diff --git a/sculpin/source/_podcast_episodes/1-retrofit.md b/sculpin/source/_podcast_episodes/1-retrofit.md new file mode 100644 index 000000000..4f949f69e --- /dev/null +++ b/sculpin/source/_podcast_episodes/1-retrofit.md @@ -0,0 +1,37 @@ +--- +date: 2023-11-10 +topic: Retrofit +guests: + - Matt Glaman +links: + - - Retrofit + - https://retrofit-drupal.com + - - Retrofit on GitHub + - https://github.com/retrofit-drupal/retrofit + - - Running legacy Drupal 7 code on your Drupal 10 site + - https://mglaman.dev/blog/retrofit-running-legacy-drupal-7-code-your-drupal-10-site + - - PHPStan + - https://phpstan.org + - - phpstan-drupal + - https://github.com/mglaman/phpstan-drupal + - - Centarro + - https://www.centarro.io + - - Drupal Commerce + - https://drupalcommerce.org + - - Matt on GitHub + - https://github.com/mglaman + - - Matt on Drupal.org + - https://www.drupal.org/u/mglaman + - - Matt on YouTube + - https://www.youtube.com/@nmdmatt + - - Matt on Twitch + - https://www.twitch.tv/mglaman +transistor: + id: 7d728873 +episode_filename: 1-retrofit.mp3 +file_size: 20523767 +duration: 0:43:52 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Matt Glaman to discuss Retrofit. A tool that makes it easier to upgrade Drupal websites by allowing legacy Drupal code to run on any version of Drupal. diff --git a/sculpin/source/_podcast_episodes/10-ryan-weaver-symfonycasts.md b/sculpin/source/_podcast_episodes/10-ryan-weaver-symfonycasts.md new file mode 100644 index 000000000..7b790cbbe --- /dev/null +++ b/sculpin/source/_podcast_episodes/10-ryan-weaver-symfonycasts.md @@ -0,0 +1,37 @@ +--- +date: 2024-02-10 +topic: Twig, Symfony and SymfonyCasts +guests: + - Ryan Weaver +transistor: + id: f276e486 +links: + - - Symfony + - https://symfony.com + - - SymfonyCasts + - https://symfonycasts.com + - - Symfony UX + - https://ux.symfony.com + - - Twig + - https://twig.symfony.com + - - Twig Components + - https://ux.symfony.com/twig-component + - - Composer + - https://getcomposer.org + - - 'Symfony: The Fast Track' + - https://symfony.com/book + - - SymfonyCasts Blog + - https://symfonycasts.com/blog + - - Ryan on Twitter + - https://twitter.com/weaverryan + - - Ryan on GitHub + - https://github.com/weaverryan + - - Ryan on YouTube + - https://www.youtube.com/@weaverryan +episode_filename: 10-symfonycasts.mp3 +file_size: 26892969 +duration: 0:53:59 +use: [podcast_episodes] +--- + +This week, Oliver is joined by Ryan Weaver - Symfony Developer, Symfony core team member and Writer for SymfonyCasts to discuss the recent developments in Twig templates, SymfonyCasts, release cycles, and similarities between the Drupal and Symfony projects and communities. diff --git a/sculpin/source/_podcast_episodes/11-mark-conroy.md b/sculpin/source/_podcast_episodes/11-mark-conroy.md new file mode 100644 index 000000000..4cae1823d --- /dev/null +++ b/sculpin/source/_podcast_episodes/11-mark-conroy.md @@ -0,0 +1,35 @@ +--- +date: 2024-02-16 +topic: Build something useful in one day +guests: + - Mark Conroy +transistor: + id: c2c3f7b3 +links: + - - mark.ie + - https://mark.ie + - - Annertech + - https://www.annertech.com + - - Running Plan Generator + - https://runningplangenerator.com + - - Web Component Design System + - https://web-components-design-system.mark.ie +talking_points: + - Building better websites faster, including Drupal distributions, such as LocalGov. + - What Drupal gives you out of the box and using the right tool for the job. + - Drupal migrations and migrating Drupal configuration from a spreadsheet. + - Saving time and improving efficiency by standardising base builds with Docksal and Composer. + - How to build projects, like the Running Plan Generator, in a day and training for 10Ks and marathons. + - Prioritising tasks. + - Annertech's development workflow and standardisation by developing on remote servers. + - Why you may not need preprocessors and complicated front-end build tools, and reducing complexity using vanilla CSS, JavaScript and web components. + - Lowering the barrier to entry to contribute to open-source projects. + - Building a design system/component library with web components. + - The Content Access by Path module that was developed for Essex County Council. +episode_filename: 11-something-useful.mp3 +file_size: 30369780 +duration: 1:02:28 +use: [podcast_episodes] +--- + +This week, Oliver is joined by Mark Conroy - Director of Development at Annertech - to discuss all things front-end and how to build something useful in one day. diff --git a/sculpin/source/_podcast_episodes/12-nick-janetakis-docker.md b/sculpin/source/_podcast_episodes/12-nick-janetakis-docker.md new file mode 100644 index 000000000..f2361913e --- /dev/null +++ b/sculpin/source/_podcast_episodes/12-nick-janetakis-docker.md @@ -0,0 +1,22 @@ +--- +date: 2024-02-26 +topic: Docker +guests: + - Nick Janetakis +transistor: + id: a0498296 +links: + - - Nick's website and blog + - https://nickjanetakis.com + - - Nick on YouTube + - https://www.youtube.com/@NickJanetakis + - - Nick's Docker example repositories on GitHub + - https://github.com/nickjj?tab=repositories&q=-example +talking_points: [] +episode_filename: 12-docker.mp3 +file_size: 28021353 +duration: 0:51:48 +use: [podcast_episodes] +--- + +This week, Oliver is joined by Nick Janetakis - a Software Developer, Docker Captain and Teacher who focuses on building and deploying web apps - to discuss Docker, content creation and more. diff --git a/sculpin/source/_podcast_episodes/13-ryan-szrama-centarro.md b/sculpin/source/_podcast_episodes/13-ryan-szrama-centarro.md new file mode 100644 index 000000000..b8f8f2f92 --- /dev/null +++ b/sculpin/source/_podcast_episodes/13-ryan-szrama-centarro.md @@ -0,0 +1,63 @@ +--- +date: 2024-03-04 +topic: Centarro and Drupal Commerce +guests: + - Ryan Szrama +transistor: + id: ab539bef +links: + - - Centarro + - https://www.centarro.io + - - Ryan on Twitter + - https://twitter.com/ryanszrama + - - Ryan on Drupal Answers + - https://drupal.stackexchange.com/users/866/ryan-szrama +talking_points: + - eCommerce, Ubercart and Drupal Commerce. + - How Commerce Guys started. + - How Ryan started in the eCommerce space. + - The origins of Drupal Commerce and Commerce Guys. + - Commerce Kickstart. +quotes: + - The best code isn't the most novel or most compact, it's the most easily readable and easily extendable (RS). + - My only resource for learning PHP was php.net (RS) + - I'm a self-taught Developer or community-taught, I suppose (OD). + - Porting osCommerce into Drupal, which became Ubercart (RS). + - Do we do this in Ubercart and Drupal 6 that we know works, or this new thing that was Drupal Commerce in Drupal 7 (OD). + - It was built in Ubercart and was in production until quite recently, considering we're in 2024 (OD). + - Once you get thoroughly entrenched in a platform, the cost to re-platform outweighs the cost of maintaining it in-house (RS). + - If there's 10,000 of anybody, they're going to want to pay for support (RS). + - How do we convince them to invest in an upgrade that doesn't see them jettison Drupal entirely? (RS) + - One thing I like about Drupal Commerce is its flexibility. (OD) + - It doesn't need to be a t-shirt or book shop. You can do some outside the box things with it. (OD) + - Being a native extension of Drupal has a lot more advantages and pros than cons. (RS) + - Ubercart was more "batteries included" and "this is what it does", whereas Drupal Commerce is more flexible and although it requires a bit more setup to begin with, you can plug it together the way you want to. (OD) + - Our vision was to go the next step of getting off the Drupal island. (RS) + - The Commerce Addressing library is now over 17,000,000 downloads. (OD) + - Composer allowed us to separate our projects and separate our concerns. (RS) + - Do you know when you should not use Views and when you decouple that component and use JavaScript and the REST API? (RS) + - If we can reduce the number of times introduce those kinds of problems, that's how I would certify somebody. (RS) +chapters: + - 00:00 Introduction and DrupalCon Lille. + - 6:00 How did you get started in software development? + - 17:36 Getting into eCommerce. + - 19:14 The origins of Commerce Guys and Drupal Commerce. + - 20:26 How Oliver started with eCommerce projects. + - 22:68 Ubercart for Drupal 7? + - 30:04 Commerce Kickstart. + - 34:08 Commerce flexibility. + - 35:52 More commerce Kickstart. + - 38:62 Ubercart and Commerce differences. + - 40:34 The Commerce Kickstart project template. + - 42:50 Building Drupal Commerce 2. + - 46:38 Releasing new things. + - 51:58 Certified Centarro partners? + - 57:38 Centarro roadmap. + - 62:06 Wrapping up. +episode_filename: 13-drupal-commerce.mp3 +file_size: 30353061 +duration: 1:03:36 +use: [podcast_episodes] +--- + +This week, Oliver is joined by Ryan Szrama, CEO of Centarro, to discuss Drupal Commerce, Commerce Kickstart, Mario Kart and the dreaded `cache_form` table. diff --git a/sculpin/source/_podcast_episodes/14-yuri-gerasymov-diffy.md b/sculpin/source/_podcast_episodes/14-yuri-gerasymov-diffy.md new file mode 100644 index 000000000..1ab9c3551 --- /dev/null +++ b/sculpin/source/_podcast_episodes/14-yuri-gerasymov-diffy.md @@ -0,0 +1,45 @@ +--- +date: 2024-03-11 +topic: Diffy and Visual Regression Testing +guests: + - Yuri Gerasymov +transistor: + id: 5940d69f +links: + - - About Yuri + - https://ygerasimov.com/about-me + - - Diffy + - https://diffy.website + - - Yuri on Drupal.org + - https://www.drupal.org/u/ygerasimov +talking_points: + - What is visual regression testing? + - How do you deal with false positives? + - Different use cases for visual regression testing. + - Automatic updates. + - Scheduling content. + - Visual regression testing in CI. + - Diffy in WordPress. + - What's a baseline? + - Initial setup and onboarding feedback. + - Testing dark mode? + - Component testing with Storybook and Fractal? + - Testing local environments. + - Testing as authenticated users. + - The roadmap for Diffy. +quotes: + - We help development teams to have less visual bugs in their website. We take screenshots of the pages and compare them so you can see what changed and how. (YG) + - We built tools for you to mock the content. You provide selectors for the elements with the content of the article and we'll replace it with lorem ipsum text so it will be exactly the same across multiple environments. (YG) + - I can still write an assertion to check the text is on the page or not, but it won't confirm it's in the correct place. (OD) + - Having a tool checking for changes on a regular basis instead of only after a deployment would be very useful. (OD) + - So, you could have a tool like Violinst automatically creating pull requests and Diffy checking those PRs, so the two could work together? (OD) + - With visual testing, it's very easy to get started. (YG) + - Visual testing is great for showing your client your work. (YG) +chapters: [] +episode_filename: 14-diffy.mp3 +file_size: 22892297 +duration: 0:46:25 +use: [podcast_episodes] +--- + +This week, Oliver discusses visual regression testing and Diffy with Yuri Gerasymov. diff --git a/sculpin/source/_podcast_episodes/15-rob-allen-domain-driven-design.md b/sculpin/source/_podcast_episodes/15-rob-allen-domain-driven-design.md new file mode 100644 index 000000000..45c4c7a19 --- /dev/null +++ b/sculpin/source/_podcast_episodes/15-rob-allen-domain-driven-design.md @@ -0,0 +1,51 @@ +--- +date: 2024-03-20 +topic: Domain-Driven Design +guests: + - Rob Allen +transistor: + id: 0de0b405 +links: + - - Rob's blog + - https://akrabat.com + - - Nineteen Feet + - https://19ft.com +talking_points: + - Rebuild vs. rewrite. + - Writing good commit messages. + - Are code comments useful? + - Technical Design Documents and ADRs. + - Ubiquitous language and Domain-Driven Design. + - PHP UK, PHP South West, conferences and user groups. + - DDD in Drupal? + - DRY and YAGNI. + - When to refactor? +quotes: + - I quite like legacy projects because i think they've already proved their worth in the marketplace. (RA) + - I general, I think that rewriting the wrong approach nearly every single time. (RA) + - Things are so impermanent. The only things you can trust are in the source code and what's in the revision history of that source code. + - We have the "what" but we don't have the "why". (OD) + - As you do this for longer, I think you start picking up on what you wish you'd written in the past. (RA) + - I think nearly everything related to software development that really matters is invariably about communication. (RA) + - Nearly everything that results in good quality software is because good communication works. (RA) + - Ubiquitous language is using the same language the specialists are using. (RA) + - An awful lot about DDD is trying to get the communication right. (RA) + - If you pretend it's not happening, it doesn't mean it's not happening - just that you're ignoring the problem. (RA) + - It's cheaper to fix things earlier in the process. (RA) + - User groups are such a good community resource. We get to try thing (talks) out. (RA) + - A conference gives you a focused block of time to learn something. (RA) + - I think the tenets of DDD can are important regardless (of the size of the project). (RA) + - We can refactor our way out, but now the overall time is longer. (RA) + - Time spent upfront is tangible effect on the time spent later. (RA) + - The biggest one [benefit of DDD] is that you end up with a project that's fit for purpose. + - You're way more likely to deliver a project that does what the customer needs if you have listened and understood what they said. (RA) + - It's in the customer's best interest for you to get it right the first time. (OD) + - You have to be proactive. It doesn't happen by default. (RA) +chapters: [] +episode_filename: 15-ddd.mp3 +file_size: 24444165 +duration: 0:56:08 +use: [podcast_episodes] +--- + +This week, Oliver discusses Domain-Driven Design with PHP UK speaker, Rob Allen. diff --git a/sculpin/source/_podcast_episodes/16-simon-graham-weight-loss.md b/sculpin/source/_podcast_episodes/16-simon-graham-weight-loss.md new file mode 100644 index 000000000..aaf898714 --- /dev/null +++ b/sculpin/source/_podcast_episodes/16-simon-graham-weight-loss.md @@ -0,0 +1,20 @@ +--- +date: 2024-05-01 +topic: Health, fitness and weight loss +guests: + - Simon Graham +transistor: + id: da3e6309 +links: + - - simongpt.co.uk + - https://www.simongpt.co.uk +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 16-health-fitness-weight.mp3 +file_size: 22258088 +duration: 0:42:06 +use: [podcast_episodes] +--- + +This week, Oliver discusses health, fitness and weight loss with Personal Trainer and Weight Loss Coach, Simon Graham. diff --git a/sculpin/source/_podcast_episodes/17-jochen-lillich.md b/sculpin/source/_podcast_episodes/17-jochen-lillich.md new file mode 100644 index 000000000..310c23bb2 --- /dev/null +++ b/sculpin/source/_podcast_episodes/17-jochen-lillich.md @@ -0,0 +1,28 @@ +--- +date: 2024-07-18 +topic: Automation, Linux training and mechanical keyboards +guests: + - Jochen Lillich +transistor: + id: d8858593 +links: + - - Jochen's personal website + - https://www.geewiz.dev + - - Jochen on Twitch + - https://www.twitch.tv/monospacementor + - - monospacementor.com + - https://monospacementor.com + - - freistil.it + - https://www.freistil.it +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 17-automation-linux.mp3 +file_size: 26449557 +duration: 0:54:23 +use: [podcast_episodes] +--- + +This week, Oliver is joined by the Monospace Mentor - Jochen Lillich. + +Jochen and I discuss content creation, live streaming on Twitch and YouTube, infrastructure automation, Linux, mentoring and, of course, mechanical keyboards. diff --git a/sculpin/source/_podcast_episodes/18-andy-hoang.md b/sculpin/source/_podcast_episodes/18-andy-hoang.md new file mode 100644 index 000000000..fd7867db6 --- /dev/null +++ b/sculpin/source/_podcast_episodes/18-andy-hoang.md @@ -0,0 +1,24 @@ +--- +date: 2024-08-09 +topic: LEGO, robotics and open-source software +guests: + - Andy Hoang +transistor: + id: 82fb51bf +links: + - - Beyond Blocks website + - https://www.beyondblocks.co.uk + - - Open Web Alliance + - https://www.drupal.org/association/blog/drupal-association-co-founds-the-open-website-alliance + - - Open Source Initiative + - https://opensource.org +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 18-lego-robotics.mp3 +file_size: 25854381 +duration: 0:51:06 +use: [podcast_episodes] +--- + +This week, Oliver is joined by Andy Hoang. They discuss teaching children to code with LEGO and robotics, and how to leverage open-source software. diff --git a/sculpin/source/_podcast_episodes/19-sam-mortenson.md b/sculpin/source/_podcast_episodes/19-sam-mortenson.md new file mode 100644 index 000000000..8bdcd5c94 --- /dev/null +++ b/sculpin/source/_podcast_episodes/19-sam-mortenson.md @@ -0,0 +1,30 @@ +--- +date: 2024-08-27 +topic: Single File Components and Static Drupal Websites +guests: + - Sam Mortenson +transistor: + id: 824e9f2b +links: + - - Sam Mortenson on Drupal.org + - https://www.drupal.org/u/samuelmortenson + - - Sam Mortenson on Twitter/X + - https://x.com/mortensonsam + - - mortenson.coffee + - https://mortenson.coffee + - - The Tome project on Drupal.org + - https://www.drupal.org/project/tome + - - The Bookish distribution + - https://github.com/drupal-tome/bookish + - - AwaySync + - https://awaysync.com +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 19-sfc-static-drupal.mp3 +file_size: 15153981 +duration: 0:30:58 +use: [podcast_episodes] +--- + +In this episode, Oliver speaks with Sam Mortenson (samuelmortenson) about single file components in Drupal and Tome (a Drupal-based static website generator). diff --git a/sculpin/source/_podcast_episodes/2-alternate-realities.md b/sculpin/source/_podcast_episodes/2-alternate-realities.md new file mode 100644 index 000000000..e9432f934 --- /dev/null +++ b/sculpin/source/_podcast_episodes/2-alternate-realities.md @@ -0,0 +1,29 @@ +--- +date: 2023-11-17 +topic: Drupal's Alternate Realities +guests: + - Panagiotis Moutsopoulos +links: + - - DrupalCon Lille + - https://events.drupal.org/lille2023 + - - Panagiotis' BoF session + - https://events.drupal.org/lille2023/session/drupals-alternate-realities + - - Panagiotis on Drupal.org (vensires) + - https://www.drupal.org/u/vensires + - - E-Sepia + - https://www.e-sepia.gr + - - Panagiotis on LinkedIn + - https://www.linkedin.com/in/panagiotis-moutsopoulos/ + - - https://drupal.org.gr + - https://drupal.org.gr + - - Frontend United + - https://www.frontendunited.com +transistor: + id: 5f7e3397 +episode_filename: 2-alternate-realities.mp3 +file_size: 19346455 +duration: 0:43:51 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Panagiotis Moutsopoulos to discuss about the whole first-time DrupalCon experience of Lille (France) and more specifically, his session Drupal’s Alternate Realities A BoF session presenting some history but mainly the different ways to tackle a problem in Drupal using different methodologies. diff --git a/sculpin/source/_podcast_episodes/20-george-gordon.md b/sculpin/source/_podcast_episodes/20-george-gordon.md new file mode 100644 index 000000000..ac2351b5d --- /dev/null +++ b/sculpin/source/_podcast_episodes/20-george-gordon.md @@ -0,0 +1,24 @@ +--- +date: 2024-09-06 +topic: Bootcamps, Hackathons, Meetups and Drupal +guests: + - George Gordon +transistor: + id: ec999352 +links: + - - School of Code + - https://schoolofcode.co.uk + - - Versantus + - https://www.versantus.co.uk + - - George on LinkedIn + - https://www.linkedin.com/in/george-gordon-70aa3a82 +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 20-bootcamps.mp3 +file_size: 23938605 +duration: 0:48:12 +use: [podcast_episodes] +--- + +In this episode, Oliver speaks with George Gordon - a graduate from the School of Code who was recently employed in their first Junior Developer role - about their move into tech and software development, their experiences at hack days and meetups, and their introduction to Drupal. diff --git a/sculpin/source/_podcast_episodes/21-eirik-morland-violinist-2.md b/sculpin/source/_podcast_episodes/21-eirik-morland-violinist-2.md new file mode 100644 index 000000000..2ec8a33fb --- /dev/null +++ b/sculpin/source/_podcast_episodes/21-eirik-morland-violinist-2.md @@ -0,0 +1,34 @@ +--- +date: 2024-09-13 +topic: Violinist, Render Arrays and Feature Flags +guests: + - Eirik Morland +transistor: + id: a4f651a7 +links: + - - violinist.io + - https://violinist.io + - - Violinist on Drupal.org + - https://www.drupal.org/violinist + - - Eirik on Drupal.org + - https://www.drupal.org/u/eiriksm + - - The violinist.io Roadmap + - https://violinist.io/roadmap + - - The Violinist Teams module + - https://www.drupal.org/project/violinist_teams + - - Behat + - https://behat.org + - - Feature Flags + - https://martinfowler.com/articles/feature-toggles.html + - - Deployments vs releases + - /daily/2023/06/21/deployments-or-releases +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 21-violinist.mp3 +file_size: 30666885 +duration: 1:01:55 +use: [podcast_episodes] +--- + +Oliver is joined again by Eirik Morland (the first returning guest) to discuss recent improvements and enhancements to Violinist, such as Team support (a.k.a. multi-user subscriptions). diff --git a/sculpin/source/_podcast_episodes/22-dave-liddament.md b/sculpin/source/_podcast_episodes/22-dave-liddament.md new file mode 100644 index 000000000..6419f06de --- /dev/null +++ b/sculpin/source/_podcast_episodes/22-dave-liddament.md @@ -0,0 +1,34 @@ +--- +date: 2024-09-30 +topic: Static Analysis +guests: + - Dave Liddament +transistor: + id: 9b2a9587 +links: + - - Dave's website + - https://www.daveliddament.co.uk + - - PHPStan + - https://phpstan.org + - - php-language-extensions + - https://github.com/DaveLiddament/php-language-extensions + - - Static Analysis Results Baseliner + - https://github.com/DaveLiddament/sarb + - - Types in Laravel by Nuno Maduro + - https://www.youtube.com/watch?v=jObcE58UCB8 + - - PHP South West + - https://phpsw.uk + - - Dave on X + - https://x.com/DaveLiddament + - - Dave on Mastodon + - https://mastodon.social/@daveliddament@phpc.social +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 22-static-analysis.mp3 +file_size: 25543869 +duration: 0:58:55 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Dave Liddament - Director at Lamp Bristol and Organiser of PHP South West - to discuss PHPStan and static analysis. diff --git a/sculpin/source/_podcast_episodes/23-jurgen-haas-eca.md b/sculpin/source/_podcast_episodes/23-jurgen-haas-eca.md new file mode 100644 index 000000000..3b8d24182 --- /dev/null +++ b/sculpin/source/_podcast_episodes/23-jurgen-haas-eca.md @@ -0,0 +1,26 @@ +--- +date: 2024-10-09 +topic: Drupal Events, Conditions and Actions +guests: + - Jürgen Haas +transistor: + id: f68650c9 +links: + - - Jürgen on Drupal.org + - https://www.drupal.org/u/jurgenhaas + - - ECA module + - https://www.drupal.org/project/eca + - - ECA Guide + - https://ecaguide.org + - - NWDUG talk and demo + - https://www.youtube.com/watch?v=b512Lk1PSSk +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 23-eca.mp3 +file_size: 21181821 +duration: 0:51:53 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Jürgen Haas to discuss the Drupal Event, Condition, Action (ECA) module. diff --git a/sculpin/source/_podcast_episodes/24-chris-ballard-generative-ai.md b/sculpin/source/_podcast_episodes/24-chris-ballard-generative-ai.md new file mode 100644 index 000000000..b0025e69d --- /dev/null +++ b/sculpin/source/_podcast_episodes/24-chris-ballard-generative-ai.md @@ -0,0 +1,28 @@ +--- +date: 2024-10-16 +topic: Generative AI in PHP +guests: + - Chris Ballard +transistor: + id: ab87d408 +links: + - - Chris on LinkedIn + - https://www.linkedin.com/in/chris-ballard-3b573b3 + - - Scoot Software + - https://www.scootsoftware.com + - - Byte to Eat (Chris' example application) + - https://github.com/chris-ballard/byte-to-eat + - - The Drupal AI module + - https://www.drupal.org/project/ai + - - AI content migration demo from DrupalCon + - https://youtu.be/nhPiL4g972A?si=pAQ9sPIuQqdDf3y0&t=2687 +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 24-generative-ai.mp3 +file_size: 29900397 +duration: 00:58:33 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Chris Ballard to discuss his recent talk at PHP South West about using generative AI in PHP, speaking at meetups and live coding. diff --git a/sculpin/source/_podcast_episodes/25-jess-archer-drush-laravel-prompts.md b/sculpin/source/_podcast_episodes/25-jess-archer-drush-laravel-prompts.md new file mode 100644 index 000000000..28262bcd8 --- /dev/null +++ b/sculpin/source/_podcast_episodes/25-jess-archer-drush-laravel-prompts.md @@ -0,0 +1,30 @@ +--- +date: 2024-11-07 +topic: Drush and Laravel Prompts +guests: + - Jess Archer +transistor: + id: 8f4510b0 +links: + - - Jess' website + - https://jessarcher.com + - - Jess on X + - https://x.com/jessarchercodes + - - Laravel + - https://laravel.com + - - Laravel Prompts + - https://laravel.com/docs/prompts + - - Drush + - https://www.drush.org + - - Unveiling Laravel Prompts (Laracon US 2023) + - https://youtu.be/PW-2_-KxF-8?si=7Z8i9yqxsgmi-4oH +talking_points: [] +quotes: [] +chapters: [] +episode_filename: 25-laravel-prompts.mp3 +file_size: 20523767 +duration: 1:02:41 +use: [podcast_episodes] +--- + +In this episode, Oliver and Jess Archer (Engineering Team Lead at Laravel) discuss Laravel Prompts and Drush, PHP, Linux and working on the command line with tools like Neovim and tmux. diff --git a/sculpin/source/_podcast_episodes/26-mark-conroy-the-confident.md b/sculpin/source/_podcast_episodes/26-mark-conroy-the-confident.md new file mode 100644 index 000000000..21ceb57d8 --- /dev/null +++ b/sculpin/source/_podcast_episodes/26-mark-conroy-the-confident.md @@ -0,0 +1,23 @@ +--- +date: 2024-12-31 +topic: The Confident and open source sustainability +guests: + - Mark Conroy +transistor: + id: 30d1a880 +links: + - - mark.ie + - https://mark.ie + - - LocalGov Drupal + - https://localgovdrupal.org + - - The Confident + - https://the-confident.com +quotes: [] +chapters: [] +episode_filename: 26-the-confident.mp3 +file_size: 25367036 +duration: 00:48:53 +use: [podcast_episodes] +--- + +For the final Beyond Blocks episode of 2024, I caught up with Mark Conroy to discuss changes since we spoke in February; namely leaving Annertech and setting up The Confident - a digital agency focused on LocalGov Drupal, different ways to charge for development services and being sponsored to work on open source software. diff --git a/sculpin/source/_podcast_episodes/27-drupalisms.md b/sculpin/source/_podcast_episodes/27-drupalisms.md new file mode 100644 index 000000000..c4db3945d --- /dev/null +++ b/sculpin/source/_podcast_episodes/27-drupalisms.md @@ -0,0 +1,28 @@ +--- +date: 2025-02-28 +topic: Discussing Drupalisms +guests: + - Emma Horrell + - Luke McCormick +transistor: + id: ~ +links: + - - De-jargoning Drupal – working with the community to open up Drupal’s terminology + - https://www.drupal.org/association/blog/de-jargoning-drupal-working-with-the-community-to-open-up-drupals-terminology + - - Locating Drupalisms (core issue) + - https://www.drupal.org/project/drupal/issues/3381734 + - - The Drupal terminology quiz + - https://www.drupal.org/project/drupal/issues/3480953 + - - Emma on Drupal.org + - https://www.drupal.org/u/emma-horrell + - - Luke on Drupal.org + - https://www.drupal.org/u/cellear +quotes: [] +chapters: [] +episode_filename: 27-drupalisms.mp3 +file_size: 24474764 +duration: 00:52:29 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by two guests - Emma Horrell, User Experience Manager at the University of Edinburgh, and Luke McCormick to discuss Drupalisms and Drupal's terminology, the Drupalisms working group and the work being done in Drupal and Drupal CMS to de-jargon Drupal. diff --git a/sculpin/source/_podcast_episodes/28-using-ai-tools-web-coding.md b/sculpin/source/_podcast_episodes/28-using-ai-tools-web-coding.md new file mode 100644 index 000000000..467e64b60 --- /dev/null +++ b/sculpin/source/_podcast_episodes/28-using-ai-tools-web-coding.md @@ -0,0 +1,27 @@ +--- +date: 2025-05-23 +topic: Using AI tools for web coding +guests: + - Luke McCormick +transistor: + id: ~ +links: + - - Luke on Drupal.org + - https://www.drupal.org/u/cellear + - - Web Coding for Non-Coders -- using AI, of course + - https://webcamp.stanford.edu/session/web-coding-for-non-coders-using-ai-of-course + - - Cursor - the AI text editor + - https://www.cursor.com + - - The Cache-Size-Block module + - https://github.com/cellear/Cache-Size-Block + - - Simplify Drupal + - https://simplifydrupal.com +quotes: [] +chapters: [] +episode_filename: 28-using-ai-web-coding.mp3 +file_size: 28682900 +duration: 00:56:04 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined again by Luke McCormick, this time to discuss using AI for web coding and how to simplify Drupal websites. diff --git a/sculpin/source/_podcast_episodes/29-drupal-cms-recipes.md b/sculpin/source/_podcast_episodes/29-drupal-cms-recipes.md new file mode 100644 index 000000000..04219dca2 --- /dev/null +++ b/sculpin/source/_podcast_episodes/29-drupal-cms-recipes.md @@ -0,0 +1,25 @@ +--- +date: 2025-05-30 +topic: Drupal CMS Recipes +guests: + - Gareth Alexander +transistor: + id: ~ +links: + - - The Drupal recipes cookbook + - https://www.drupal.org/docs/extending-drupal/contributed-modules/contributed-module-documentation/distributions-and-recipes-initiative/recipes-cookbook + - - The Recipes Initiative project on Drupal.org + - https://www.drupal.org/project/distributions_recipes + - - The Bad Judgement module + - https://www.drupal.org/project/bad_judgement + - - Gareth on Drupal.org + - https://www.drupal.org/u/the_g_bomb + - - Gareth's presentation at DrupalCamp England + - https://www.youtube.com/watch?v=b7MDA-kKCCk +episode_filename: 29-drupal-cms-recipes.mp3 +file_size: 30861164 +duration: 00:59:29 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Gareth Alexander - Drupal CMS Accessibility Tools Track Lead and recent speaker at DrupalCamp England - to discuss Drupal CMS recipes. diff --git a/sculpin/source/_podcast_episodes/3-non-technical-contribution.md b/sculpin/source/_podcast_episodes/3-non-technical-contribution.md new file mode 100644 index 000000000..57bd29f99 --- /dev/null +++ b/sculpin/source/_podcast_episodes/3-non-technical-contribution.md @@ -0,0 +1,33 @@ +--- +date: 2023-11-24 +topic: Community engagement for non-technical Drupal enthusiasts +guests: + - Niklas Franke +links: + - - DrupalCon Lille + - https://events.drupal.org/lille2023 + - - 'Beyond the code: Community engagement for non-technical Drupal enthusiasts' + - https://events.drupal.org/lille2023/session/beyond-code-community-engagement-non-technical-drupal-enthusiasts + - - 'How to organise your own Splash Awards' + - https://events.drupal.org/lille2023/session/how-organise-your-own-splash-awards + - - 'DrupalCon sponsored talk: What developers really want: Uncovering the essential work benefits for software developers (sponsored by Factorial)' + - https://events.drupal.org/lille2023/session/what-developers-really-want-uncovering-essential-work-benefits-software + - - 'Splash Awards' + - https://www.drupal.org/community/splash-awards + - 'Niklas Franke on Drupal.org' + - https://www.drupal.org/u/heroicnick + - - 'Factorial GmbH' + - https://www.factorial.io/en/drupal-agency + - - 'Factorial GmbH on Drupal.org' + - https://www.drupal.org/factorial-gmbh + - - 'Factorial on YouTube' + - https://www.youtube.com/channel/UCJslkuiIJLTRmYEvN2y-jzA +transistor: + id: 85bdc4c7 +episode_filename: 3-community-engagement.mp3 +file_size: 24882117 +duration: 0:50:39 +use: [podcast_episodes] +--- + +This week, Oliver is joined by Niklas Franke to discuss DrupalCon Lille, contributing to Drupal as a non-technical enthusiast, the Splash Awards and the Drupal community in Germany. diff --git a/sculpin/source/_podcast_episodes/30-growing-engineering-culture.md b/sculpin/source/_podcast_episodes/30-growing-engineering-culture.md new file mode 100644 index 000000000..0569ea448 --- /dev/null +++ b/sculpin/source/_podcast_episodes/30-growing-engineering-culture.md @@ -0,0 +1,23 @@ +--- +date: 2025-06-11 +topic: Growing Engineering Culture +guests: + - Ev Maslovskiy +links: + - - Ev on Drupal.org + - https://www.drupal.org/u/spleshka + - - SystemSeed + - https://systemseed.com + - - SystemSeed on Drupal.org + - https://www.drupal.org/systemseed + - - DrupalCamp England + - https://www.drupalcampengland.org + - - Video recording of Ev's talk + - https://www.youtube.com/watch?v=Q_9fWVCAUtU +episode_filename: 30-engineering-culture.mp3 +file_size: 30861164 +duration: 01:08:43 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Ev Maslovskiy - CTO at SystemSeed - to discuss engineering culture after his recent talk at DrupalCamp England. diff --git a/sculpin/source/_podcast_episodes/31-modeler-api.md b/sculpin/source/_podcast_episodes/31-modeler-api.md new file mode 100644 index 000000000..289dc2f51 --- /dev/null +++ b/sculpin/source/_podcast_episodes/31-modeler-api.md @@ -0,0 +1,37 @@ +--- +date: 2025-06-27 +topic: Modeler API +guests: + - Jürgen Haas +links: +- - Jürgen on Drupal.org + - https://www.drupal.org/u/jurgenhaas +- - The ECA module + - https://www.drupal.org/project/eca +- - The BPMN.iO module + - https://www.drupal.org/project/bpmn_io +- - Drupal Events, Conditions and Actions with Jürgen Haas + - /podcast/23-jurgen-haas-eca +- - Drupal Remote Dashboard + - https://www.drupal.org/project/drd +- - Drupal Recipes + - https://www.drupal.org/docs/extending-drupal/drupal-recipes +- - Discussing Drupal CMS Recipes with Gareth Alexander + - /daily/2025/06/03/discussing-drupal-cms-recipes-gareth-alexander +- - Drupal CMS + - https://www.drupal.org/project/cms +- - Discussing Drupalisms with Emma Horrell and Luke McCormick + - /podcast/27-discussing-drupalisms +- - Model Context Protocol + - https://modelcontextprotocol.io +- - The Model Context Protocol module + - https://www.drupal.org/project/mcp +- - Using AI tools for web coding with Luke McCormick + - /podcast/28-using-ai-tools-web-coding +episode_filename: 31-modeler-api.mp3 +file_size: 21761540 +duration: 00:46:05 +use: [podcast_episodes] +--- + +In this episode, Oliver is re-joined by Jürgen Haas to discuss the new Modeler API module and progress made with the ECA module. diff --git a/sculpin/source/_podcast_episodes/32-accessibility.md b/sculpin/source/_podcast_episodes/32-accessibility.md new file mode 100644 index 000000000..d3409c06d --- /dev/null +++ b/sculpin/source/_podcast_episodes/32-accessibility.md @@ -0,0 +1,39 @@ +--- +date: 2025-07-11 +topic: Web Accessibility +guests: + - Mike Gifford +links: +- - Mike's website + - https://ox.ca +- - Mike on Drupal.org + - https://www.drupal.org/u/mgifford +- - My Web, My Way + - https://www.bbc.co.uk/programmes/p005khmk +- - simplA11yPDFCrawler + - https://github.com/accessibility-luxembourg/simplA11yPDFCrawler +- - Drupal.org's Accessibility page + - https://www.drupal.org/about/features/accessibility +- - WCAG 2 Overview + - https://www.w3.org/WAI/standards-guidelines/wcag +- - Drupal's core gates + - https://www.drupal.org/about/core/policies/core-change-policies/core-gates +- - Accessibility Roles and Responsibilities Mapping (ARRM) Community Group + - https://www.w3.org/community/arrm +- - Sustainable Web Interest Group + - https://www.w3.org/groups/ig/sustainableweb +- - Writing Accessibility tests in Nightwatch + - https://www.drupal.org/docs/develop/automated-testing/javascript-testing-using-nightwatch +- - The Sa11y module + - https://www.drupal.org/project/sa11y +- - Drupal's Accessibility Coding Standards + - https://www.drupal.org/docs/develop/standards/accessibility-coding-standards +- - Shift-left testing + - https://en.wikipedia.org/wiki/Shift-left_testing +episode_filename: 32-web-accessibility.mp3 +file_size: 38235236 +duration: 01:23:01 +use: [podcast_episodes] +--- + +In this episode, Oliver is joined by Mike Gifford - Senior Strategist at CivicActions, W3C Invited Expert and Drupal Core Accessibility Maintainer - to discuss web accessibility. diff --git a/sculpin/source/_podcast_episodes/4-ed-crompton-oxfam-case-study.md b/sculpin/source/_podcast_episodes/4-ed-crompton-oxfam-case-study.md new file mode 100644 index 000000000..b60be8ad8 --- /dev/null +++ b/sculpin/source/_podcast_episodes/4-ed-crompton-oxfam-case-study.md @@ -0,0 +1,39 @@ +--- +date: 2023-12-01 +topic: A case study from Oxfam +guests: + - Ed Crompton +transistor: + id: 0ff9802a +links: + - - Ed Crompton on Drupal.org + - https://www.drupal.org/u/eddie_c + - - 'Oxfam country sites: From big bang to small batch delivery' + - https://www.linkedin.com/pulse/oxfam-country-sites-from-big-bang-small-batch-edward-crompton + - - Oxfam.org + - https://www.oxfam.org/en + - - https://cambodia.oxfam.org + - https://cambodia.oxfam.org + - - Pattern Lab + - https://patternlab.io + - - Fractal + - https://fractal.build + - - Twig + - https://twig.symfony.com + - - Working in small batches + - http://www.startuplessonslearned.com/2009/02/work-in-small-batches.html + - - Behat + - http://www.behat.org + - - Behat integration with Drupal + - https://www.drupal.org/project/behat + - - phenaproxima on Drupal.org + - https://www.drupal.org/u/phenaproxima + - - I've been using Behat wrong this whole time + - https://phenaproxima.net/2018/08/07/behat-insanity.html + - - Drupal Test Traits + - https://gitlab.com/weitzman/drupal-test-traits +episode_filename: 4-oxfam.mp3 +file_size: 21505533 +duration: 0:47:36 +use: [podcast_episodes] +--- diff --git a/sculpin/source/_podcast_episodes/5-dieter-blomme-technical-debt.md b/sculpin/source/_podcast_episodes/5-dieter-blomme-technical-debt.md new file mode 100644 index 000000000..fd07a88fd --- /dev/null +++ b/sculpin/source/_podcast_episodes/5-dieter-blomme-technical-debt.md @@ -0,0 +1,33 @@ +--- +date: 2023-12-09 +topic: Managing technical debt +guests: + - Dieter Blomme +transistor: + id: 40066a7f +links: + - - DrupalCon Lille + - https://events.drupal.org/lille2023 + - - 'Managing technical debt: lessons learned and how modern Drupal helps you' + - https://events.drupal.org/lille2023/session/managing-technical-debt-lessons-learned-and-how-modern-drupal-helps-you + - - Understanding Technical Debt in the Drupal ecosystem + - https://www.youtube.com/watch?v=1YSL4Be7jDY + - - Dieter Blomme on Drupal.org + - https://www.drupal.org/u/daften + - - Dropsolid website + - https://dropsolid.com/ + - - Dropsolid on Drupal.org + - https://www.drupal.org/dropsolid + - - Dropsolid on YouTube + - https://www.youtube.com/@dropsolid.experiencecompany + - - DrupalCon session video + - https://youtu.be/S-B7_YiskVM + - - Concerns vs objectives + - https://blog.holacracy.org/holacracy-basics-understanding-objections-d87b579d00d1 + - - Decision by traffic light + - https://www.linkedin.com/pulse/decision-making-101-traffic-lights-puppy-case-study-valerio-magliulo +episode_filename: 5-technical-debt.mp3 +file_size: 23248532 +duration: 0:52:22 +use: [podcast_episodes] +--- diff --git a/sculpin/source/_podcast_episodes/6-dan-leech-php-tui.md b/sculpin/source/_podcast_episodes/6-dan-leech-php-tui.md new file mode 100644 index 000000000..dd42a4720 --- /dev/null +++ b/sculpin/source/_podcast_episodes/6-dan-leech-php-tui.md @@ -0,0 +1,41 @@ +--- +date: 2023-12-19 +topic: 'TUIs, CLIs and open-source' +guests: + - Dan Leech +transistor: + id: 45d57d43 +links: + - - PHP TUI on GitHub + - https://github.com/php-tui + - - Phpactor on GitHub + - https://github.com/phpactor + - - PHPbench on GitHub + - https://github.com/phpbench + - - Phpactor documentation + - https://phpactor.readthedocs.io + - - PHPBench documentation + - https://phpbench.readthedocs.io + - - Testing code performance with PHPBench + - https://youtu.be/-qxu6n9Q-3k?si=2N8Ee9GIgCul7_e1 + - - PHP-TUI Progress + - https://www.dantleech.com/blog/2023/11/03/php-tui-progress + - - PHP Term + - https://www.dantleech.com/blog/2023/11/27/php-term + - - PHP Architecture Tester (phpat) + - https://github.com/carlosas/phpat + - - Jess Archer + - https://jessarcher.com + - - Neovim as a PHP and JavaScript IDE (Laracasts) + - https://laracasts.com/series/neovim-as-a-php-ide + - - Laravel Prompts + - https://github.com/laravel/prompts + - - Symfony Terminal component + - https://speakerdeck.com/fabpot/the-symfony-terminal-component +episode_filename: 6-tuis-clis.mp3 +file_size: 22071243 +duration: 0:53:17 +use: [podcast_episodes] +--- + +In this week's episode, Oliver is joined by Dan Leech to discuss building command-line applications and TUIs with PHP based on Dan's open-source projects - Phpactor, PHPBench and, most recently, PHP-TUI. diff --git a/sculpin/source/_podcast_episodes/7-mike-karthauser-testing-legacy.md b/sculpin/source/_podcast_episodes/7-mike-karthauser-testing-legacy.md new file mode 100644 index 000000000..c9efdb416 --- /dev/null +++ b/sculpin/source/_podcast_episodes/7-mike-karthauser-testing-legacy.md @@ -0,0 +1,39 @@ +--- +date: 2024-01-10 +topic: Testing Legacy +guests: + - Mike Karthauser +transistor: + id: c264ca69 +links: + - - Huboo + - https://huboo.com + - - PHPUnit + - https://phpunit.de + - - Laravel + - https://laravel.com + - - Expression Engine + - https://expressionengine.com + - - PHPBench + - https://phpbench.com + - - Working in small batches + - http://www.startuplessonslearned.com/2009/02/work-in-small-batches.html + - - Cyclomatic complexity + - https://en.wikipedia.org/wiki/Cyclomatic_complexity + - - Shopify + - https://www.shopify.com + - - Drupal Commerce + - https://drupalcommerce.org + - - PHP South West + - https://phpsw.uk + - - Automica labs + - https://automica.io + - - Mike on LinkedIn + - https://www.linkedin.com/in/mikekarthauser +episode_filename: 7-testing-legacy.mp3 +file_size: 24294452 +duration: 0:53:23 +use: [podcast_episodes] +--- + +Oliver and Mike discuss e-commerce, legacy code, technical debt, automated testing, test-driven development, refactoring, code vs. no-code solutions, and Mike's recent talk at PHP South West in Bristol. diff --git a/sculpin/source/_podcast_episodes/8-eirik-morland-violinist.md b/sculpin/source/_podcast_episodes/8-eirik-morland-violinist.md new file mode 100644 index 000000000..f61aa67e4 --- /dev/null +++ b/sculpin/source/_podcast_episodes/8-eirik-morland-violinist.md @@ -0,0 +1,31 @@ +--- +date: 2024-01-29 +topic: Violinist and automation +guests: + - Eirik Morland +transistor: + id: ba4405e5 +links: + - - violinist.io + - https://violinist.io + - - Violinist on Drupal.org + - https://www.drupal.org/violinist + - - Eirik on Drupal.org + - https://www.drupal.org/u/eiriksm + - - Composer + - https://getcomposer.org + - - Packagist + - https://packagist.org + - - Private Packagist + - https://packagist.com + - - Automatic Updates initiative + - https://www.drupal.org/about/core/strategic-initiatives/automatic-updates + - - Logo is a conductor, not a composer + - https://github.com/composer/getcomposer.org/issues/36 +episode_filename: 8-violinist.mp3 +file_size: 27664298 +duration: 1:00:01 +use: [podcast_episodes] +--- + +Oliver and Eirik Morland discuss automated dependency updates with Violinist, PHP and Composer, why automation is good, and focusing on providing value for clients and customers. diff --git a/sculpin/source/_podcast_episodes/9-tim-lehnen.md b/sculpin/source/_podcast_episodes/9-tim-lehnen.md new file mode 100644 index 000000000..62e918080 --- /dev/null +++ b/sculpin/source/_podcast_episodes/9-tim-lehnen.md @@ -0,0 +1,39 @@ +--- +date: 2024-02-05 +topic: The Drupal Association +guests: + - Tim Lehnen +links: + - - Drupal Association + - https://www.drupal.org/association + - - Drupal recognized as a Digital Public Good + - https://dri.es/drupal-recognized-as-a-digital-public-good + - - Drupal Association elections + - https://www.drupal.org/association/board/elections + - - Find a Drupal 7 migration partner + - https://www.drupal.org/about/drupal-7/d7eol/partners + - - Join partner programs + - https://www.drupal.org/association/programs + - - Drupal Events + - https://events.drupal.org + - - Drupal Jobs + - https://jobs.drupal.org + - - GitLab + - https://www.gitlab.com + - - GitLab CI on Drupal.org + - https://www.drupal.org/docs/develop/git/using-gitlab-to-contribute-to-drupal/gitlab-ci + - - Tim on Drupal.org + - https://www.drupal.org/u/hestenet + - - Tim on Twitter + - https://twitter.com/TimLehnen +transistor: + id: e5d5ba38 +episode_filename: 9-drupal-association.mp3 +file_size: 36650781 +duration: 1:06:23 +use: [podcast_episodes] +--- + +This week, Oliver is joined by Tim Lehnen - the CTO of the Drupal Association. + +They discuss what is the Drupal Association is and does, how companies and individuals can contribute and support the Association, some recent and upcoming improvements to Drupal.org, Drupal 7's end-of-life, and more. diff --git a/sculpin/source/_posts/1.md b/sculpin/source/_posts/1.md new file mode 100644 index 000000000..58b4ae468 --- /dev/null +++ b/sculpin/source/_posts/1.md @@ -0,0 +1,36 @@ +--- +title: Ellipsis in pager template fails accessibility tests +date: '2024-08-21 12:00:00' +tags: + - Drupal + - Accessibility + - ARIA + - Software Development + - Web Development +note: true +permalink: /notes/1-ellipsis-in-pager-template-fails-accessibility-tests +--- + +```html +