Based on our assessment of CRLA's most important audience and goals—working class, immigrant, and bilingual potential clients need to be able to find questions or get in contact—we identified the following as important elements of their homepage:
You will learn to use the Migrate API to upgrade your Drupal 6/7 site to Drupal 11. Check how the automated upgrade procedure can help you get a head start in writing the migrations. You will learn different migration strategies, how to accommodate changes in site architecture, tips on troubleshooting issues, and much more.
With the maturity of Drupal 11, now is a great time to upgrade your site from Drupal 6 or 7.
There will be plenty of hands on examples to demonstrate different migration strategies even for projects that do not offer automatic upgrade paths. Time will also be allocated to answer attendee’s project specific questions for topics not covered in the predefined material.
You have used Rabbit Hole module to prevent people from being able to directly visit to select content items, but when you include those items in a reference list Drupal is still linking to them.
Here is one way to fix that.
This presumes you are listing nodes, taxonomy terms, or other content entities with some that are set to not allow direct visiting, but that the others should be linked. Essentially, if you have configured a content type, vocabulary, or other bundle in Rabbit Hole to Allow these settings to be overridden for individual entities, and are using this capability, you may be in a situation where item A links to its page, item B should not because that page will give access denied or page not found, and item C perhaps should link to its page, etc.
First, if the list is shown as labels, Rabbit Hole Links module is all you need. Install it, enable it, you are done— no configuration needed, and no need for the rest of this blog post.
However, if you are listing content rendered as view modes, that module will not handle the links for you. In our case, we have a "Person" content type and are using Entity Reference Override module to show a varied project role alongside the person's name. As some of the people should be linked, and others should not have standalone pages, we needed a way to deactivate links based on the per-node Rabbit Hole settings.
This approach follows the path laid out by Daniel Flanagan of Horizontal using bundle classes to provide control over node URLs. Laying out that path for us all to follow also involved Daniel building several bridges, in the form of four patches (which all apply to the current stable versions of these modules, but work is needed to keep up with the latest development branches and get these patches in):
As Daniel Flanagan's blog post also helpfully provides, here are the composer patches that need to go in the patches section (under extra) of your project's composer.json file:
"patches": {
"drupal/core": {
"Path module calls getInternalPath without checking if the url is routed": "https://www.drupal.org/files/issues/2023-05-03/3342398-18-D9.patch"
},
"drupal/pathauto": {
"deleteEntityPathAll calls getInternalPath on potentially unrouted url": "https://www.drupal.org/files/issues/2023-05-03/pathauto-unrouted-3357928-2.patch",
"Alias should not get created if system path is <nolink>": "https://www.drupal.org/files/issues/2023-06-15/pathauto-nolink-3367043-2.patch"
},
"drupal/redirect": {
"redirect_form_node_form_alter calls getInternalPath on potentially unrouted url": "https://www.drupal.org/files/issues/2023-02-16/redirect-unrouted-3342409-2.patch"
},
},
And with that, you are ready for the code!
First, you may need to make the link conditional on a URL existing in your template. Here is our node--person--project-details-team.html.twig for showing the person's name (node title) linked to their page (if applicable) followed by their project role (if any, we made this a field not shown on the Person edit form but only in the Entity Reference Override widget form used when the person is referenced from a project).
{% if url %}<a href="{{ url }}">{% endif %}{{ label }}{% if url %}</a>{% endif %}{% if node.field_project_title.value %}{{- content.field_project_title -}}{% endif %}
In a custom module, called here example module, first in you example.module file have your bundle class take over for the specified content type:
<?php
/**
* Implements hook_entity_bundle_info_alter().
*/
function example_entity_bundle_info_alter(array &$bundles): void {
if (isset($bundles['node']['person'])) {
$bundles['node']['person']['class'] = \Drupal\example\Entity\Bundle\PersonNode::class;
}
}
In your same custom module, make file at src/Entity/Bundle/PersonNode.php:
<?php
namespace Drupal\example\Entity\Bundle;
use Drupal\node\Entity\Node;
use Drupal\Core\Url;
/**
* A bundle class for node entities.
*/
class PersonNode extends Node {
/**
* Use contents of field_link as canonical url.
*
* {@inheritdoc}
*/
public function toUrl($rel = 'canonical', array $options = []) {
if ($rel === 'canonical' && $this->hasField('rabbit_hole__settings')) {
if ($this->get('rabbit_hole__settings')->action === 'access_denied') {
return new Url('<nolink>');
}
}
return parent::toUrl($rel, $options);
}
/**
* {@inheritdoc}
*
* This is important to avoid accidentally having pathauto delete all url aliases.
* @see https://www.drupal.org/project/pathauto/issues/3367067
*/
public function hasLinkTemplate($rel) {
if ($rel === 'canonical' && $this->hasField('rabbit_hole__settings')) {
if ($this->get('rabbit_hole__settings')->action === 'access_denied') {
return FALSE;
}
}
return parent::hasLinkTemplate($rel);
}
}
The above works for our setup (where we only set individual items to access denied, and we know the default will always be to show the page), but the way we get the settings for rabbit hole should be updated and follow the approach in Rabbit Hole Links, which would be more robust.
Overriding this in a way a contributed module could do (so not bundle classes) should be possible but the need to unset canonical links to use uri_callback and then reproduce the canonical link logic for all bundles that you do not want to affect—all while Drupal wants to deprecate uri_callback in routes for entities—makes this a not-fun contrib experience. But possibly Rabbit Hole Links module will be up for the task!
I'd also love to hear from Typed Entity aficionados if this is possible with that alternative to bundle classes, and if so how!
Therapy Fidelity is a mobile interface that displays 132 sequential steps of cognitive behavioral therapy (CBT) for treating posttraumatic stress disorder (PTSD) to improve the fidelity of following the treatment protocol.
Leaders in the field of psychotherapy have been encouraging psychotherapists to adopt evidence-based treatments such as CBT for 20 years but it has been largely unsuccessful. Therapists have been unwilling and unable to rigorously follow CBT protocols with fidelity. Therapists cannot memorize all 132 steps, and patients have very limited access to the steps. As a result, treatment of patients suffers.
Child psychiatrist Michael Scheeringa, MD identified a solution for this problem—a mobile interface that displays a CBT treatment protocol and that can be viewed by therapists and patients simultaneously. Through the guidance of Dr. Scheeringa and in partnership with Tulane University, Agaric developed the Therapy Fidelity web app.
When a patient attends their therapy session, it is far more likely that they arrive with a mobile phone than with a laptop. The need for a seamless mobile experience was one major reason we decided to build Therapy Fidelity as a single page application using React.js. Single page applications are great for reducing the number of network calls made to the host server since they do not need to request markup templates every time an end-user clicks to a different part of the site.
Consequently, most of the network calls made by the app are made to read or write data to one of several third party APIs. We worked to mitigate these, too, by using the React Query library, a powerful and configurable tool for fetching, caching, and updating data in React. The result is an app that clearly indicates when data is loading, allows the user to continue navigating the app while update requests are being processed, indicates the results of those requests once they resolve, and prevents redundant fetching of data that has already been cached—in other words, a fast, smooth, and intuitive end-user experience, even on a limited-bandwidth device. One additional benefit of the data caching—many third party APIs will bill per API call after a limited number of requests; without caching that data in the browser, these API services could get expensive fast.
Throughout the building process, we looked to Tailwind UI for example components. By doing so, we made sure that the app has a consistent look and feel and is responsive so that it looks good on devices of all screen sizes. As this app mostly functions as a utility dashboard, the pre-designed components sufficed for the apps aesthetic needs, meaning that Tailwind UI saved us a lot of time on design work. Often we had to make minor adjustments to the markup so that it would suit our specific needs, and very seldom did we need to add any custom classes to our CSS stylesheet, which incidentally results in removing the often expensive overhead of building and maintaining our CSS architecture. Again, this is great for an app with simple aesthetic needs but which also needs re-usable and flexible responsive components.
In order to facilitate a quickest time-to-market, we opted to utilize an existing HIPAA certified provider for the storage, retrieval, and access controls/monitoring of protected data. TrueVault provides a JavaScript library for communicating with their RESTful backend. Their backend includes provisions for dealing with all aspects of the data, such as authentication, authorization, logging, and so-on. We were able to use their Vault-based data model to separate patient records into individual silo's per-therapist, and use their group-based security to set nearly all relevant permissions for the app's use. TrueVault certainly comes with its limitations and challenges, but it sure would have taken quite a bit more time and resources to build and certify a custom storage system.
Additionally, we needed to ensure that each client's data is stored and retrieved accurately. TypeScript, which provides a type system for JavaScript, helped to ensure that as our application passed data around, it was of the expected type. Using a typed language also reduces the possibility for software errors generally. Beyond using good tools to write the application, checks must be in place to ensure that as it evolves, things do not break. Here, we leveraged React Testing framework and other tools to walk through the functionality of the application and ensure that everything continued to function correctly, and even stored the correct data; By mocking (simulating) the TrueVault service we could inspect what the application would be storing there directly.
While the majority of permissions available to a logged in client were sufficient, there were cases where privileged tasks needed to be performed. Therapy Fidelity's People Like Me system is a great example. People Like Me involves a multi-step form which upon completion shows how many people with similar conditions were able to significantly improve their condition following the successful completion of a 3 month adherence to therapy protocol:
First, a patient selects for comparison the results of a single survey they have completed, consisting of numerical indicators for several psychological conditions (anxiety, depression, PTSD, etc.)
Second, they configure which parameters they would like to match on. For example, a patient could choose to only see how many people who had shared a similar pre-therapy anxiety score were able to improve their condition following therapy.
Finally, they view the results.
Now it must be acknowledged that this system is parsing through and accessing patient data in real time. Of course, it would be a breach of patient privacy law for the patient to have such access to all of this other patient data, so we made sure that all data was scrubbed before reaching storage to reduce any personally identifiable information, and that computations occurred securely on a server before serving back results to the client.
Rather than utilize something like a full VPS server that performed these functions for us, we were able to leverage functions-as-a-service to provide the specific privileged function access, specifically AWS Lambda functions. This helped us keep the surface area of the application as low as possible for security purposes, while providing server-side style functionality. The language we chose for these was Go, for its performance, excellent built-in framework, and because we were able to build for our needs with very minimal additional libraries, which again helps mitigate security concerns.
While these functions-as-a-service were used several times throughout the site, it will be hard to forget Dr. Scheeringa's excitement about the realization of the People Like Me tool.
Therapy Fidelity was an excellent development experience—both for the thrill of developing a single page app and for carrying on Agaric's history of building tools for medical and scientific communities. As always, we are looking forward to our next opportunity to engage in these communities and build something wonderful.
For any clinicians who happen to be reading this and are interested in using the Therapy Fidelity app for their own practice, Scheeringa Mind offers it as a service and provides a 30-day free trial. There are also plenty of video tutorials on how to use the app, which might help to preview just what you might be getting into.
As Scheeringa Mind Company grows and Therapy Fidelity sees more use, we will be sure to publish any updates or major achievements. We are anticipating great strides in research on CBT protocol and look forward to seeing the results.
What'd we get wrong? What resources are we missing? Send us a note or tell us in the comments below!
Con un nuevo y mejorado flujo de trabajo, el equipo de Portside ahora puede redactar, revisar y programar eficientemente videos y artículos para sus lectores.
Desde que lanzamos el nuevo diseño en febrero de 2018, portside.org ha visto un aumento del 39% en los usuarios que visitan el sitio, un aumento del 23% en las visitas a las páginas, un aumento del 13% en la duración de la sesión y una disminución complementaria del 11% en la tasa de rebote. Esto es todo a pesar de los cambios en el algoritmo de Facebook que afectaron gravemente a Portside y otras editoriales independientes.
Continuamos trabajando con Portside para monitorear el desempeño del sitio, encontrando formas adicionales de mejorar el sitio y contribuir a los medios independientes y de izquierda que son tan críticos en estos tiempos.
Congratulations to the new leadership committee for May First People Link!
Agaric is proud and excited to be a member of this organization, building fantastic shared internet resources out of open source free software, immense volunteer time, and member's dues.
Principles developed in a time-limited, collaborative-technology-driven process:
1. Bring our political processes and technology -- including resources, communication and support systems -- to a point at which all members of May First/People Link can have confidence in the reliability and control of their data. It is important to recognize varying levels of skill and interest in understanding technology.
2. Define what engaged membership in MF/PL actually means. This definition must come from the membership itself, prioritizing grassroots groups of people who face racial, gender, economic or other form of oppression, and who are currently MF/PL members in name but might not feel themselves to be members in practice. The definition should also draw from existing models of membership in our movements. This includes identifying rights and responsibilities of membership as well as opportunities for members to become more actively involved. The responsibilities and expectations of members to other members and to MFPL as a whole will be included.
[This principle, in particular, had every group's endorsement before a last-minute change.]
3. Development of governance models for Mayfirst/PeopleLink as a membership organization, drawing from the experience and expertise of members and member organizations.
4. Develop and build direct contact relationships with progressive organizations locally and internationally, and raise our visibility in public discussions, debates, and decisions. This is about (1) defining use of and choice of technology as political within our movements, and (2) contributing to debates about the internet including privacy, corporate and government surveillance, data sovereignty, censorship, and access.
5. May First/People Link will fully claim its role in building an international, alter-globalization movement by continuing our involvement in such movements as the Social Forum, Climate Change and the Palestinian rights. This would/could engage our membership in several ways: organizing delegations of members to summit events and relying on the political experience of our membership to guide our region- and sector-specific work.
6. Continue the existing collaboration with members the Praxis Project, the Progressive Technology Project, and others, to train activists of color to become more capable technologists, and expand that work to include women, and people from less traditional backgrounds. Also, continue giving support to and building on current training initiatives, while working towards the future to expand training programs in the Global South with partners and member organizations as opportunities are identified.