Planet Drupal

Syndicate content
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 40 min 10 sec ago

Freelock : Fixing Drupal 8.3 upgrade issues - TwigExtension, Layouts, and Tweaks

Thu, 06/08/2017 - 02:00
div class=g-plusone-wrapper style=margin: 0 1em 1em 1em;float:right g:plusone href=https://www.freelock.com/blog/john-locke/2017-06/fixing-drupal-83-upgrade-issues-twigextension-layouts-and-tweaks size=medium annotation=bubble width=250 /g:plusone/divdiv class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item evenpLots of stuff has been changing in Drupal 8 recently. In 8.3.0, a new experimental layout discovery module was added to core, which conflicted with the contrib layout plugin module. Now in 8.3.3, the two-column and three-column layouts had their region names changed, which hid any content dropped into those regions when those layouts were used./p pIn the past week, we've seen a couple issues upgrading a site from 8.2.x to 8.3.2, and now another issue with 8.3.2 to 8.3.3 that seem worth a quick mention./p/div/div/divdiv class=field field-name-taxonomy-vocabulary-5 field-type-taxonomy-term-reference field-label-hiddendiv class=field-itemsdiv class=field-item evena href=/tag/drupalDrupal/a/divdiv class=field-item odda href=/tag/drupal-8Drupal 8/a/divdiv class=field-item evena href=/tag/drupal-planetDrupal Planet/a/divdiv class=field-item odda href=/tag/updatesUpdates/a/divdiv class=field-item evena href=/tag/visual-regression-testingVisual Regression Testing/a/div/div/div

Lullabot: The Ten Commandments of a New Drupal 8 Site for Enterprise Developers

Wed, 06/07/2017 - 22:50
div class=rich-textdiv class=rich-text__contentpOver the past two years, I#x2019;ve had the opportunity to work with many different clients on their Drupal 8 site builds. Each of these clients had a large development team with significant amounts of custom code. After a recent launch, I went back and pulled together the common recommendations we made. Here they are!/p h21. Try to use fewer repositories and projects/h2 pWith the advent of a href=https://getcomposer.org/Composer/a for Drupal site building, it feels natural to have many small, individual repositories for each custom module and theme. It has the advantage of feeling familiar to the contrib workflow for Drupal modules, but there are significant costs to this model that only become obvious as code complexity grows./p pThe first cost is that at best, every bit of work requires two pull requests; one pull request in a custom module repository, and a second commit in the codecomposer.lock/code in the site repository. It#x2019;s easy to forget about that second pull request, and in our case, it led to constant questioning by the QA team to see if a given ticket was ready to test or not./p pA second cost is dealing with cross-repository dependencies. For example, in site implementations, it#x2019;s really common to do some work in a custom module and then to theme that work in a custom theme. Even if there#x2019;s only a master branch, there would still be three pull requests for this work#x2014;and they all have to be merged in the right order. With a single repository, you have a choice. A single pull request can be reviewed and merged, or multiple can be filed./p pA third, and truly insidious cost is where separate repositories actually become co-dependent, and no one knows it. This can happen when modules are only tested in the context of a single site and database, and not as site-independent reusable modules. Is your QA team testing each project against a stock Drupal install as well as within your site? Are they mixing and matching different tags from each repository when testing? If not, it#x2019;s better to just have a single site repository./p h22. Start with fewer branches, and add more as needed/h2 pSometimes, it feels good to start a new project by creating all of the environment-specific branches you know you#x2019;ll need; develop, qa, staging, master, and so on. It#x2019;s important to ask yourself; is each branch being used? Do we have environments for all of these branches? If not, it#x2019;s totally OK to start with a single master branch. If you do have multiple git repositories, ask this question for each repository independently. Perhaps your site repository has several branches, while the new SSO module that you#x2019;re building for multiple sites sticks with just a master branch. Branches should have meaning. If they don#x2019;t, then they just confuse developers, QA, and stakeholders, leading to deployment mistakes. Delete them./p h23. Avoid parallel projects/h2 pOnce you do have multiple branches, it#x2019;s really important to ensure that branches are eventually merged #x201C;upstream.#x201D; With Composer, it#x2019;s possible to have different codecomposer.json/code files in each branch, such as codeqa/code pointing to the codedevelop/code in each custom module, and codestaging/code pointing to codemaster/code. This causes all sorts of confusion because it effectively means you have two different software products#x2014;what QA and developers use, and what site users see. It also means that changes in the project scaffolding have to be done once in each branch. If you forget to do that, it#x2019;s nothing but pain trying to figure it out! Instead, use environment branches to represent the state of another branch at a given time, and then tag those branches for production releases. That way, you know that tag code1.3.2/code is identical to some build on your codedevelop/code branch (even if the hash isn#x2019;t identical due to merge commits)./p h24. Treat merge conflicts as an opportunity/h2 pI#x2019;ve heard from multiple developers that the real reason for individual repositories for custom modules is to #x201C;reduce merge conflicts.#x201D; Let#x2019;s think about the effect multiple repositories have on a typical Drupal site./p pI like to think about merge conflicts in three types. First, there#x2019;s the emtraditional/em merge conflict, such as when git refuses to merge a branch automatically. Two lines of code have been changed independently, and a developer needs to resolve them. Second, there are emlogical/em merge conflicts. These don#x2019;t cause a merge conflict that version control can detect but do represent a conflict in code. For example, two developers might add the same method name to a class but in different text locations in the class. Git will happily merge these together, but the result is invalid PHP code. Finally, there are emfunctional/em merge conflicts. This is where the PHP code is valid, but there is a regression or unexpected ~~behaviour~~ behavior in related code./p pSplit repositories don#x2019;t have much of an effect on traditional merge conflicts. I#x2019;ve found that split repositories make logical conflicts a little harder to manage. Typically, this happens when a base class or array is modified and the developer misses all of the places to update code. However, split repositories make functional conflicts drastically more difficult to handle. Since developers are working in individual repositories, they may not always realize that they are working at cross-purposes. And, when there are dependencies between projects, it requires careful merging to make sure everything is merged in the right order./p pIf developers are working in the same repository, and discover a merge conflict, it#x2019;s not a blocker. It#x2019;s a chance to make a friend! By discussing the conflict, it gives developers the chance to make sure they are solving the right problem, the right way. If conflicts are really complex, it#x2019;s an opportunity to either refactor the code or to raise the issue to the rest of the team. There#x2019;s nothing more exciting than realizing that a merge conflict revealed conflicting requirements./p h25. Setup config management early/h2 pI#x2019;ve seen several Drupal 8 teams delay in setting up a deployment workflow that integrates with Drupal 8#x2019;s configuration management. Instead, deployments involve pushing code and manual UI work, clicking changes together. Then, developers pull down the production database to keep up to date./p pUnfortunately, manual configuration is prone to error. All it takes is one mistake, and valuable QA time is wasted. Also, it avoids code review of configuration, which is actually possible and emenjoyable/em with Drupal 8#x2019;s YAML configuration exports./p pThe nice thing about configuration management tooling is it typically doesn#x2019;t have any dependency on your actual site requirements. This includes:/p ulliMaking sure each environment pulls in updated configs on deployment/li liAborting deployments and rolling back if config imports fail/li liGetting the development team comfortable with config basics/li liSetting up the secure use of API keys through a href=https://www.drupal.org/docs/8/api/configuration-api/configuration-override-systemenvironment variables and settings.php/a./li /ul pDoing these things early will pay off tenfold during development./p h26. Secure sites early/h2 pI recently worked on a site that was only a few weeks away from the production launch. The work was far enough along that the site was available outside of the corporate VPN under a #x201C;beta#x201D; subdomain. Much to my surprise, the site wasn#x2019;t under HTTPS at all. As well, the Drupal admin password was the name of the site!/p pThese weren#x2019;t things that the team had forgotten about; but, in the rush of the last few sprints, it was clear the two issues weren#x2019;t going to be fixed until a few days before launch. HTTPS setup, in particular, is a great example of an early setup task. Even if you aren#x2019;t on your production infrastructure, set up SSL certificates anyway. Treat any new environments without SSL as a launch blocker. Consider using a href=https://www.letsencrypt.orgLetapos;s Encrypt/a if getting proper certificates is a long task./p pThis phase is also a good chance to make sure admin and editorial accounts are secure. We recommend that the admin account password is set to a long random string#x2014;and then, don#x2019;t save or record the password. This eliminates password sharing and encourages editors to use their own separate accounts. Site admins and ops can instead use ssh and codedrush user-login/code to generate one-time login links as needed./p h27. Make downsyncs normal/h2 pCopying databases and file systems between environments can be a real pain, especially if your organization uses a custom Docker-based infrastructure. codersync/code doesn#x2019;t work well (because most Docker containers don#x2019;t run ssh), and there may be additional networking restrictions that block the usual codesql-sync/code commands./p pThis leads many dev teams to really hold off on pulling down content to lower environments because it#x2019;s such a pain to do. This workflow really throws QA and developers for a loop, because they aren#x2019;t testing and working against what production actually is. Even if it has to be entirely custom, it#x2019;s worth automating these steps for your environments. Ideally, it should be a one-button click to copy the database and files from one environment to a lower environment. Doing this early will improve your sprint velocity and give your team the confidence they need in the final weeks before launch./p h28. Validate deployments/h2 pWhen deploying new code to an environment, it#x2019;s important to fail builds if something goes wrong. In a typical Drupal site, you could have errors during:/p ullicodecomposer install/code/li licodedrush updatedb/code/li licodedrush config-import/code/li liThe deployment could work, but the site could be broken and returning codeHTTP 500/code error codes/li /ul pEach deployment should capture the deployment logs and store them. If any step fails, subsequent steps should be aborted, and the site rolled back to its previous state. Speaking of#x2026;/p h29. Automate backups and reverts/h2 pWhen a deployment fails, it should be nearly automatic to revert the site to the pre-deployment state. Since Drupal updates involve touching the database and the file system, those should both be reverted. Database restores tend to be fairly straight forward, though filesystem restores can be more complex if they are stored on S3 or some other service. If you#x2019;re hosted on AWS or a similar platform, a href=http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.htmluse their APIs and utilities to manage backups/a and restores where possible. They have internal access to their systems, making backups much more efficient. As a side benefit, this helps make downsyncs more robust, as they can be treated as a restore of a production backup instead of a direct copy./p h210. Remember #cache/h2 pOk, I suppose I mean #x201C;remember caching everywhere,#x201D; though in D8 it seems like render cache dependencies are what#x2019;s most commonly forgotten. It#x2019;s so easy to fall into Drupal 7 patterns, and just create render arrays as we always have. After all, on locals, everything works fine! But, forgetting to use codeaddCacheableDependencies/code on render arrays leads to confusing bugs down the line./p pAlong the same lines, it#x2019;s important to set up invalidation caching early in the infrastructure process. Otherwise, odds are you#x2019;ll get to the production launch and be forced to rely on TTL caches simply because the site wasn#x2019;t built or tested for invalidation caching. It#x2019;s a good practice when setting up a reverse proxy to let Drupal maintain the caching rules, instead of creating them in the proxy itself. In other words, respect codeCache-Control/code and friends from upstream systems, and only override them in very specific cases./p pFinally, be sure to test on locals with caches enabled. Sure, disable them while writing code, but after turn them back on and check again. I find incognito or private browsing windows invaluable here, as they let you test as an anonymous user at the same time as being logged in. For example, did you just add a config form that changes how the page is displayed? Flip a setting, reload the page as anonymous, and make sure the update is instant. If you have to do a codedrush cache-rebuild/code for it to work, you know you#x2019;ve forgotten code#cache/code somewhere./p pWhat commandments did I miss in this list? Post below and let me know!/p pemHeader image from a href=https://commons.wikimedia.org/wiki/File:Power_plant_control_room.jpgControl room of a power plant/a./em/p /div/div

myDropWizard.com: WIEGO: 6 years and 22,000 articles - a Drupal Non-Profit Case Study!

Wed, 06/07/2017 - 22:14
div class=field field-name-field-featured-image field-type-image field-label-hiddendiv class=field-itemsdiv class=field-item evenimg class=panopoly-image-half src=https://www.mydropwizard.com/sites/default/files/styles/panopoly_image_half/public/blog/wiego-logo.png?itok=pImkNfgn alt=WIEGO //div/div/divdiv class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item evenpAs part of our series discussing the use of Drupal in non-profits (a href=http://mydropwizard.us11.list-manage.com/subscribe?u=cf55ac86688c7c9af3e8c68aaamp;id=59683efefeamp;group%5B16357%5D%5B1%5D=1click here to subscribe via e-mail/a), we recently reached out to one of our favorite clients, a href=http://www.wiego.org/WIEGO/a, who candidly shared some of their struggles and successes./ppstrongSince re-launching their site on Drupal almost 6 years ago, they've grown from a site with 50 static pages, to a searchable, categorized repository of news and knowledge spanning over 22,000 articles!/strong/ppIn this case study, we gain some insights into how organizations like WIEGO decided on Drupal, have lived with some of the growing-pains, and are planning to move forward into the future!/ppstrongRead more to find out!/strong/pp/div/div/div

Palantir: Starwood Retail Partners

Wed, 06/07/2017 - 18:56
spanStarwood Retail Partners/span img src=https://www.palantir.net/files/hero/2017-06/case-study-starwood.jpg width=1300 height=731 alt=Photo of site displayed on tablet typeof=foaf:Image /spana title=View user profile. href=https://www.palantir.net/people/alex-brandt lang= about=https://www.palantir.net/people/alex-brandt typeof=schema:Person property=schema:name datatype= xml:lang=brandt/a/span spanWed, 06/07/2017 - 11:56/span Providing Flexibility for Future Growth div class=lede pA robust style guide translated into a flexible Drupal 8 interface./p /div Highlights ulli pEasy-to-use Drupal 8 interface/p /li li pRobust style guide/p /li li pCollaborative partnership with Petrick Design/p /li /ulsection class=ctah3 class=cta__title /h3pWe want to make your project a success./p span class=cta__link a href=https://www.palantir.net/contactLet's Chat./a /span /sectionh2Our Client/h2 pa href=https://starwoodretail.com/lease-from-us/our-propertiesStarwood Retail Partners/a owns 28 shopping malls and lifestyle centers across the United States. Unlike their competitors, Starwood Retail focuses on developing community centers instead of just shopping destinations. Their corporate website targets retailers and investors who are interested in leasing or developing their properties. The site provides information on the individual locations, as well as downloadable resources for potential investors./p pBeing on a tight timeline to launch the new site before an upcoming corporate event, Starwood Retail sought to replace their standard development partner. They had already contracted with another firm, Petrick Design, to provide creative support, but they needed a strategic development partner. After conversations with the Palantir team, Starwood Retail knew they had found the Drupal prowess they were looking for./p blockquote pWe could tell the expertise we were getting in Drupal, and that we were going to have the necessary support to get all of the things we didn’t know we needed.” — Brian Price, Digital Marketing Manager/p /blockquote h2Goals and Direction/h2 pStarwood Retail felt that their site was lagging behind their competitors, and they wanted to do a full redesign in a way that would allow them to provide thorough information with an updated look. They wanted their website to inspire, engage, and “wow” visitors while advancing the company brand and culture – innovative, creative, fresh, and young but with tremendous experience. The site also needed to intuitively expedite the leasing process, showcase their centers as prime opportunities, reinforce their retail expertise, instill pride in current employees, and inspire potential employees and partners./p pSimply put, none of the content on the old Starwood Retail site described what services they provided. It had information scattered across different pages in a way that made the information feel overwhelming, and the content was not organized at a property level. This made it extremely difficult to find location-specific information because all of their content was shown in massive lists./p pThe new site needed to achieve three primary goals:/p ullistrongSurface content/strong to make it easier for marketers, future tenants and investors to find what they needed./li listrongTell a story/strong about the services Starwood Retail provides./li listrongModernize the site/strong by migrating to Drupal 8./li /ulh2How We Helped/h2 h3Living Style Guide/h3 pStarwood Retail is a rapidly growing company, and they needed a site that had the flexibility to grow with them. We took the beautiful static designs provided by Petrick and extended them into a responsive style guide that informed the Drupal build. This robust browser-based style guide turned the design into components, so that new content can be published quickly as Starwood Retail continues to grow. This style guide now serves as a reference so that any future updates will still maintain the design system./p h3Flexibility in Drupal 8/h3 pAfter the style guide was created, it was translated into an easy-to-use Drupal interface. As we were building, we were able to show the Starwood Retail team how all of the components would come together, and we worked with them on help text, labels, and an organization that made sense to them. Since they were in on the process, it makes it easier for them to carry forward./p pThe new site is easier to understand and easier to populate. In the previous site, contact information would have to be updated in each location that it was present on the site. On the new site, if you update a piece of content, it will update that node across the whole site. Another example is that when a new mall page is added, that mall is automatically added to their location map (shown below)./p figure role=groupimg alt=Property map with advanced filtering abilities data-entity-type=file data-entity-uuid=8db455d6-7c91-496b-9e65-4ec028074f7d src=https://www.palantir.net/files/inline-images/81d8c3bce50bd57197cc6b4d5d27b49c_1.gif /figcaptionProperty map with advanced filtering abilities./figcaption/figureh2The Results/h2 pThe new Drupal 8 site has intuitive workflows and allows the editorial team to be more efficient as Starwood Retail grows. Not only does it have a modern look and feel, it’s easy to update. Editors know exactly where they need to go, because the site functions as they intended it to./p pThis project is a prime example of how a collaborative process can turn out well. Through constant communication and clearly identified trade-offs, even a very tight deadline was achieved./p blockquote p“We have a great corporate website now that everyone is really proud of, and it functions exactly how we wanted it to.” - Brian Price, Digital Marketing Manager/p /blockquote aside class=ctah3 class=cta__title /h3pWe want to make your project a success./p span class=cta__link a href=https://www.palantir.net/contactLet's Chat./a /span /asideul class=list--simpleli class=taga href=https://www.palantir.net/services/development hreflang=enDevelopment/a/li li class=taga href=https://www.palantir.net/services/front-end-development hreflang=enFront-end Development/a/li /ula href=https://www.palantir.net/technology/drupal-8 hreflang=enDrupal 8/a h3Services/h3 development a href=https://starwoodretail.com/starwoodretail.com/a

Palantir: GenomeWeb

Wed, 06/07/2017 - 18:29
spanGenomeWeb/span img src=https://www.palantir.net/files/hero/2017-06/case-study-genome.jpg width=1300 height=731 alt=Photo of 360Dx site shown on mobile device typeof=foaf:Image /spana title=View user profile. href=https://www.palantir.net/people/alex-brandt lang= about=https://www.palantir.net/people/alex-brandt typeof=schema:Person property=schema:name datatype= xml:lang=brandt/a/span spanWed, 06/07/2017 - 11:29/span Increasing Engagement Using Segmented Content div class=lede pUsing Domain Access to manage content between multiple sites./p /div Highlights ulli pMulti-headed Drupal architecture/p /li li pAudience segmentation using domain-specific registrations/p /li li pEfficient editorial and user management workflows/p /li /ulsection class=ctah3 class=cta__title /h3pWe want to make your project a success./p span class=cta__link a href=https://www.palantir.net/contactLet's Chat./a /span /sectionh2Our Client/h2 pa href=https://www.genomeweb.com/about-usGenomeWeb/a is an independent news organization that provides online reporting on genomic technologies. Historically they have focused on this very narrow niche of the bio industry, and they are the leading news site in that particular field. Their site has an active community with over 200,000 users and about 20 new articles being published daily./p pOver time GenomeWeb saw that the technologies they were covering were moving very quickly into healthcare and diagnostics, and they wanted to expand their news coverage into the molecular diagnostics space./p h2Goals and Direction/h2 pInstead of adding new content directly to the existing site, GenomeWeb wanted to create a new sister site to be located at www.360Dx.com, which would include existing diagnostic content and also new coverage that could be marketed to a broader diagnostics audience. The new site would host less technical and more business-focused content, as well as share content with the current GenomeWeb site./p pemGoals for the new 360Dx site and multi-headed architecture: /em/p ulliContent from each site should be easily accessible for both sets of audiences./li liNew clinical content should only live on 360Dx./li liSites should keep the same user database. If someone is a user on GenomeWeb, they should have the same level of access on the new 360 site. This means paying for a premium level of access on one site would grant users premium access on the other./li /ulblockquote p“It was a very complex project. The site was already complicated to begin with.” — Bernadette Toner, CEO/p /blockquote h2How We Helped/h2 pTo extend their business model to another site, Palantir used the a href=https://drupal.org/project/domainDomain module/a suite to enable editors to assign content to both genomeweb.com and 360Dx.com. With Domain, the two sites can share some content and cross-promote articles to new audiences while having unique themes and settings./p pThe team developed a new derivative theme for 360Dx.com and ensured that content, users, and views were assigned to the proper domain. This work included analysis of existing modules and content, the creation and testing of update scripts, and configuration of domain-specific settings for analytics, ads, and other services. We also worked with the GenomeWeb team to integrate domains into their memberships, so that users could subscribe to email news bulletins from either or both sites independently./p pThe new site structure we created had very intuitive workflows, which meant the GenomeWeb team did not need extensive training to learn the new functionality. We worked to ease deployment and updates using the Features modules and through documentation of domain configurations./p h2The Results/h2 pThe new multi-headed Drupal architecture created multiple wins for GenomeWeb. There is a wealth of content between their two sites, and by using Domain Access they are able to easily manage it all in one place. It has been easy for editors to post content and decide if it should go to one site or both, and there hasn’t been a huge change in their daily workflow./p pThe new architecture also allows GenomeWeb to engage with their audience on a deeper level: by having different kinds of registrations for each site, GenomeWeb is able to collect different demographics and target specific segments of their audience with more data. Although the site is still new, GenomeWeb has met their initial projections, and they anticipate being able to personalize their efforts even more as more data compiles./p blockquote p“The new site works as we envisioned, which doesn’t always happen. The Palantir team listened to what we needed and was able to make it happen, and we are really, really happy with the results.” — Bernadette Toner, CEO/p /blockquote “The new site works as we envisioned, which doesn’t always happen. The Palantir team listened to what we needed and was able to make it happen, and we are really, really happy with the results.” Bernadette Toner, CEO aside class=ctah3 class=cta__title /h3pWe want to make your project a success./p span class=cta__link a href=https://www.palantir.net/contactLet's Chat./a /span /asideul class=list--simpleli class=taga href=https://www.palantir.net/industries/healthcare hreflang=enHealthcare/a/li li class=taga href=https://www.palantir.net/industries/media hreflang=enMedia/a/li /ulul class=list--simpleli class=taga href=https://www.palantir.net/services/development hreflang=enDevelopment/a/li li class=taga href=https://www.palantir.net/services/information-architecture hreflang=enInformation Architecture/a/li /ula href=https://www.palantir.net/technology/drupal-8 hreflang=enDrupal 8/a h3Services/h3 development a href=https://www.genomeweb.com/genomeweb.com/a a href=https://www.360dx.com/360Dx.com/a

Jacob Rockowitz: Crowdfunding does not help grow Drupal's community

Wed, 06/07/2017 - 18:07
pFirst off, I want emphasize that the below blog post is my opinion and personal feelings as someone who has spent the past year building the Webform 8.x-5.x module for the Drupal community. Now I want to see it continue to grow and flourish. There are many thought leaders, including Dries, that have contemplated and publicly discussed the concept and benefits of crowdfunding and have used this approach to fund Drupal 8 a href=http://buytaert.net/announcing-the-drupal-8-accelerate-fundcore/a and a href=http://buytaert.net/a-map-for-accelerating-drupal-8-adoptionmodule/a development./ppDrupal 8 was, and still is, a monolithic accomplishment - one that continues to be an ambitious undertaking to maintain and improve. The Drupal community might still be waiting for Drupal 8 to be released if organizations did not crowdfund and accelerate D8. It is our togetherness, our pooling of our resources, that allows us to accomplish great things, like Drupal. At the same time, the Drupal community is made up of a network of relationships and collaborations. Drupal and Open-source’s success depends on its collaborative community, which is driven by relationships. Crowdfunding solves a big problem, pooling resources to fund open source, but it does not build relationships. Drupal's strength lies in its community, bonded together by healthy and productive relationships./ppI feel that crowdfunding, especially within the Drupal contributed project space, is just handing out fish without teaching project maintainers how to fish or even companies how to properly hand out fish. Crowdfunding Drupal projects does not build relationships between project maintainers and organizations/companies. The most obvious issue is that crowdfunding typically has a limited number of fish. Conversely, dozens of companies are throwing fish, aka money, into a pool that is drained by project maintainers, who don't even know the origin of this particular fish. Finally, the most...a href=http://www.jrockowitz.com/blog/crowdfundingRead More/a

Bluespark Labs: When Drupal Met CARTO

Wed, 06/07/2017 - 16:50
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even pimg alt= height=455 src=https://www.bluespark.com/files/resources/carto-diagram.png width=810 //p pa href=https://www.drupal.org/8Drupal 8/a is a powerful and customizablenbsp;CMS./p pIt provides a lot of different tools to add, store, and visualize data, however spatial data visualizationnbsp;is a sophisticated and complicated topic — and Drupal hasn't always beennbsp;the best option for handling it./p pBecause of its complexity, spatial data requires a specific process to become visual. We oftennbsp;think of a map with some pins or location points, but there are much more complex edge cases where Drupal is not able to solve the end user needs, such as rendering thousands of points or complex geometries in a map, or trying to create heatmaps based on stored data./p pThat’s why it's important to acknowledge that Drupal is not a golden hammer and the use of third party services will help us to provide a much better and appropriate user experience. This is where we introducenbsp;a href=https://carto.com/CARTO/a./p pCARTO is a powerful spatial data analysis platform that provides different services related to the geographical information stored in a spatial database in the cloud. The fact that the base of all this process is a database table makes the connection between Drupal and CARTO simple and fairly straightforward./p pFrom our point of view, two ofnbsp;the most useful tools provided by CARTO to be integrated within Drupal are the Import API and Builder. (There are some other ones that are interesting for more advanced users)./p ul lia href=https://carto.com/docs/carto-engine/import-apiImport API/a allows you to upload files to a CARTO account, check on their current upload status, as well as delete and list importing processes on a given account./li lia href=https://carto.com/builder/CARTO Builder/a is a web-based drag and drop analysis tool for analysts and business users to discover and predict key insights from location data. Maps generated with this tool can be shared or embedded in any website./li /ul pSo, at this point we have two systems — Drupal and CARTOnbsp;— with the followingnbsp;features:/p ul liDrupal, a very capable tool to create, store, and establish relationships between content/li liCARTO, a powerful platform able to import spatial data, process it and generate amazing performancenbsp;maps that can be shared/li liDrupal Media, an ecosystem that allows embedding and integratingnbsp;external resources as entities/li /ul pThe problem is generatingnbsp;powerful maps emand/em includingnbsp;themnbsp;in any Drupal site./p pFirst, the data stored in Drupal has to be pushed to CARTO. Then the maps are generated in CARTOnbsp;before being embedded in Drupal.nbsp;/p pThis can now easily be done usingnbsp;a href=https://www.drupal.org/project/carto_syncCARTO Sync/a and a href=https://www.drupal.org/project/media_entity_cartoMedia entity CARTO/a, both Drupal modules./p ul liCARTO Sync allows Drupal Views to generatenbsp;who's results can be pushed to CARTO to be processed/li liMedia Entity CARTO integrates CARTO Builder shared maps within the Media ecosystem and allows to create Mapnbsp;entities to be referenced or embedded in any Drupal content/li /ul pFollowingnbsp;this method,nbsp;we can still use Drupal as the CMS, while taking advantage of all the features that CARTO provides in order to represent accuratenbsp;spatial information./p pIf you find this topic interesting, please take a look at thenbsp;a href=http://goo.gl/3Xm26pslides/a ornbsp;a href=https://vimeo.com/217956217recording/a from the presentation atnbsp;a href=https://2017.drupalcamp.es/DrupalCamp Madrid 2017/a./p /div/div/divdiv class=field field-name-field-blog-tags field-type-taxonomy-term-reference field-label-abovediv class=field-labelTags:nbsp;/divdiv class=field-itemsdiv class=field-item evena href=/blog/drupal-planetDrupal Planet/a/divdiv class=field-item odda href=/blog/cartoCARTO/a/divdiv class=field-item evena href=/blog/drupal-8Drupal 8/a/divdiv class=field-item odda href=/blog/spatial-dataspatial data/a/divdiv class=field-item evena href=/blog/mappingmapping/a/div/div/div

Flocon de toile | Freelance Drupal: Create a mega menu with Drupal 8

Wed, 06/07/2017 - 12:00
div class=field field--name-body field--type-text-with-summary field--label-hidden field--itempCreating a responsive mega menu is often a regular prerequisite on any project, Drupal 8 or other. And if we can find some solutions offering to create mega menus easily, very often these solutions remain quite rigid and can hardly be adapted to the prerequisites of a project. But what is a mega menu? It is nothing more than a menu that contains a little more than a list of links (proposed by the menu system of Drupal 8), with specific links, text, images, call to actions, etc./p/div

Sudhanshu Gautam | Blog: GSoC 2017 | Week 1: Port Vote Up/Down

Wed, 06/07/2017 - 08:11
span property=schema:name class=field field--name-title field--type-string field--label-hiddenGSoC 2017 | Week 1: Port Vote Up/Down/span span rel=schema:author class=field field--name-uid field--type-entity-reference field--label-hiddenspan lang= about=http://sudhanshug.com/blog/user/1 typeof=schema:Person property=schema:name datatype= xml:lang=sudhanshu/span/span span property=schema:dateCreated content=2017-06-07T06:11:02+00:00 class=field field--name-created field--type-created field--label-hiddenWed, 06/07/2017 - 11:41/span

OhTheHugeManatee: Stop Waiting for Feeds Module: How to Import RSS in Drupal 8

Wed, 06/07/2017 - 06:33
pHow do you import an RSS feed into entities with Drupal 8? In Drupal 6 and 7, you probably used the a href=https://drupal.org/project/feedsFeeds/a module. Feeds 7 made it easy (-ish) to click together a configuration that matches an RSS (or any XML, or CSV, or OPML, etc) source to a Drupal entity type, maps source data into Drupal fields, and runs an import with the site Cron. Where has that functionality gone in D8? I recently had to build a podcast mirror for a client that needed this functionality, and I was surprised at what I found./p pstrongFeeds module/strong doesnrsquo;t have a stable release candidate, and it doesnrsquo;t look like one is coming any time soon. Theyrsquo;re still surveying people about what feeds module should even DO in D8. As the module page explains:/p blockquotepIt#8217;s not ready yet, but we are brainstorming about what would be the best way forward. Want to help us? Fill in our survey.br/If you decide to use it, don#8217;t be mad if we break it later./p/blockquote p/p pThis does not inspire confidence./p pThe next great candidate is a href=https://www.drupal.org/docs/8/core/modules/aggregator/overviewAggregator/a module (in core). Unfortunately, Aggregator gives you no control over the kind of entity to create, let alone any kind of field mapping. It imports content into its own Aggregated Content entity, with everything in one field, and linking offsite. I suppose you could extend it to choose you own entity type, map fields etc, but that seems like a lot of work for such a simple feature./p pFrustrating, right?/p pstrongWhat if I told you that Drupal 8 can do everything Feeds 7 can?/strong/p pWhat if I told you that itrsquo;s even better: instead of clicking through endless menus and configuration links, waiting for things to load, missing problems, and banging your head against the mouse, you can set this up with one simple piece of text. You can copy and paste it directly from this blog post into Drupalrsquo;s admin interface./p h2What? How?/h2 pDrupal 8 can do all the Feedsy stuff you like with a href=https://www.drupal.org/docs/8/api/migrate-api/migrate-api-overviewMigrate/a module. Migrate in D8 core already contains all the elements you need to build a regular importer of ANYTHING into D8. Add a couple of contrib modules to provide specific plugins for XML sources and convenience drush functions, and embaby yoursquo;ve got a stew goin#8217;!/em/p pHerersquo;s the short version Howto:/p pstrong1) Download and enable a href=https://drupal.org/project/migrate_plusmigrate_plus/a and a href=https://drupal.org/project/migrate_toolsmigrate_tools/a modules./strong You should be doing this with composer, but I wonrsquo;t judge. Just get them into your codebase and enable them. Migrate Plus provides plugins for core Migrate, so you can parse remote XML, JSON, CSV, or even arbitrary spreadsheet data. Migrate Tools gives us drush commands for running migrations./p pstrong2) Write your Migration configuration in text/strong, and paste it into the configuration import admin page (codeadmin/config/development/configuration/single/import/code), or import it another way. Irsquo;ve included a starter YAML just below, you should be able to copypasta, change a few values, and be done in time for tea./p pstrong3) Add a line to your system cron/strong to run codedrush migrate -y my_rss_importer/code at whatever interval you like./p pThatrsquo;s it. One YAML file, most of which is copypasta. One cronjob. All done!/p pHerersquo;s my RSS importer config for your copy and pasting pleasure. If yoursquo;re already comfortable with migration YAMLs and XPaths, just add the names of your RSS fields as selectors in the source section, map them to drupal fields in the process section, and yoursquo;re all done!/p pIf you arenrsquo;t familiar with this stuff yet, donrsquo;t worry! Wersquo;ll dissect this together, below./p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span span class='line-number'5/span span class='line-number'6/span span class='line-number'7/span span class='line-number'8/span span class='line-number'9/span span class='line-number'10/span span class='line-number'11/span span class='line-number'12/span span class='line-number'13/span span class='line-number'14/span span class='line-number'15/span span class='line-number'16/span span class='line-number'17/span span class='line-number'18/span span class='line-number'19/span span class='line-number'20/span span class='line-number'21/span span class='line-number'22/span span class='line-number'23/span span class='line-number'24/span span class='line-number'25/span span class='line-number'26/span span class='line-number'27/span span class='line-number'28/span span class='line-number'29/span span class='line-number'30/span span class='line-number'31/span span class='line-number'32/span span class='line-number'33/span span class='line-number'34/span span class='line-number'35/span span class='line-number'36/span span class='line-number'37/span span class='line-number'38/span span class='line-number'39/span span class='line-number'40/span span class='line-number'41/span span class='line-number'42/span span class='line-number'43/span span class='line-number'44/span span class='line-number'45/span span class='line-number'46/span span class='line-number'47/span span class='line-number'48/span span class='line-number'49/span span class='line-number'50/span span class='line-number'51/span span class='line-number'52/span span class='line-number'53/span span class='line-number'54/span span class='line-number'55/span span class='line-number'56/span span class='line-number'57/span span class='line-number'58/span span class='line-number'59/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plainid/spanspan class=p-Indicator:/span span class=l-Scalar-Plainmy_rss_importer/span /spanspan class='line'span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=s#39;Import/spanspan class=nv /spanspan class=smy/spanspan class=nv /spanspan class=sRSS/spanspan class=nv /spanspan class=sfeed#39;/span /spanspan class='line'span class=l-Scalar-Plainstatus/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintrue/span /spanspan class='line' /spanspan class='line'span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainurl/span /spanspan class='line' span class=l-Scalar-Plaindata_fetcher_plugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainhttp/span /spanspan class='line' span class=l-Scalar-Plainurls/spanspan class=p-Indicator:/span span class=s#39;https://example.com/feed.rss#39;/span /spanspan class='line' span class=l-Scalar-Plaindata_parser_plugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsimple_xml/span /spanspan class='line' /spanspan class='line' span class=l-Scalar-Plainitem_selector/spanspan class=p-Indicator:/span span class=l-Scalar-Plain/rss/channel/item/span /spanspan class='line' span class=l-Scalar-Plainfields/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainguid/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainGUID/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-Plainguid/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintitle/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainTitle/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintitle/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpub_date/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=s#39;Publication/spanspan class=nv /spanspan class=sdate#39;/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-PlainpubDate/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainlink/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=s#39;Origin/spanspan class=nv /spanspan class=slink#39;/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-Plainlink/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsummary/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainSummary/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=s#39;itunes:summary#39;/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainimage/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainImage/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=s#39;itunes:image[/spanspan class=se#39;#39;/spanspan class=shref/spanspan class=se#39;#39;/spanspan class=s]#39;/span /spanspan class='line' /spanspan class='line' span class=l-Scalar-Plainids/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainguid/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaintype/spanspan class=p-Indicator:/span span class=l-Scalar-Plainstring/span /spanspan class='line' /spanspan class='line'span class=l-Scalar-Plaindestination/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=s#39;entity:node#39;/span /spanspan class='line' /spanspan class='line'span class=l-Scalar-Plainprocess/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaintitle/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintitle/span /spanspan class='line' span class=l-Scalar-Plainfield_remote_url/spanspan class=p-Indicator:/span span class=l-Scalar-Plainlink/span /spanspan class='line' span class=l-Scalar-Plainbody/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsummary/span /spanspan class='line' span class=l-Scalar-Plaincreated/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainformat_date/span /spanspan class='line' span class=l-Scalar-Plainfrom_format/spanspan class=p-Indicator:/span span class=s#39;D,/spanspan class=nv /spanspan class=sd/spanspan class=nv /spanspan class=sM/spanspan class=nv /spanspan class=sY/spanspan class=nv /spanspan class=sH:i:s/spanspan class=nv /spanspan class=sO#39;/span /spanspan class='line' span class=l-Scalar-Plainto_format/spanspan class=p-Indicator:/span span class=s#39;U#39;/span /spanspan class='line' span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpub_date/span /spanspan class='line' span class=l-Scalar-Plainstatus/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plaindefault_value/span /spanspan class='line' span class=l-Scalar-Plaindefault_value/spanspan class=p-Indicator:/span span class=l-Scalar-Plain1/span /spanspan class='line' span class=l-Scalar-Plaintype/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plaindefault_value/span /spanspan class='line' span class=l-Scalar-Plaindefault_value/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpodcast_episode/span /span/code/pre/td/tr/table/div/figure pSome of you can just stop here. If yoursquo;re familiar with the format and the structures involved, this example is probably all you need to set up your easy RSS importer./p pIn the interest of good examples for Migrate module though, Irsquo;m going to continue. Read on if you want to learn more about how this config works, and how you can use Migrate to do even more amazing thingshellip;/p h2Anatomy of a migration YAML/h2 pLetrsquo;s dive into that YAML a bit. Migrate is one of the most powerful components of Drupal 8 core, and this configuration is your gateway to it./p pThat YAML looks like a lot, but itrsquo;s really just 4 sections. They can appear in any order, but we need all 4: General information, source, destination, and data processing. This isnrsquo;t rocket science after all! Letrsquo;s look at these sections one at a time./p pstrongGeneral information/strong/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plainid/spanspan class=p-Indicator:/span span class=l-Scalar-Plainmy_rss_importer/span /spanspan class='line'span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=s#39;My/spanspan class=nv /spanspan class=sRSS/spanspan class=nv /spanspan class=sfeed/spanspan class=nv /spanspan class=simporter#39;/span /spanspan class='line'span class=l-Scalar-Plainstatus/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintrue/span /span/code/pre/td/tr/table/div/figure pThis is the basic stuff about the migration configuration. At a minimum it needs a unique machine-readable ID, a human-readable label, and codestatus: true/code so itrsquo;s enabled. There are other keys you can include here for fun extra features, like module dependencies, groupings (so you can run several imports together!), tags, and language. These are the critical ones, though./p pstrongSource/strong/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span span class='line-number'5/span span class='line-number'6/span span class='line-number'7/span span class='line-number'8/span span class='line-number'9/span span class='line-number'10/span span class='line-number'11/span span class='line-number'12/span span class='line-number'13/span span class='line-number'14/span span class='line-number'15/span span class='line-number'16/span span class='line-number'17/span span class='line-number'18/span span class='line-number'19/span span class='line-number'20/span span class='line-number'21/span span class='line-number'22/span span class='line-number'23/span span class='line-number'24/span span class='line-number'25/span span class='line-number'26/span span class='line-number'27/span span class='line-number'28/span span class='line-number'29/span span class='line-number'30/span span class='line-number'31/span span class='line-number'32/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainurl/span /spanspan class='line' span class=l-Scalar-Plaindata_fetcher_plugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainfile/span /spanspan class='line' span class=l-Scalar-Plainurls/spanspan class=p-Indicator:/span span class=s#39;https://example.com/feed.rss#39;/span /spanspan class='line' span class=l-Scalar-Plaindata_parser_plugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsimple_xml/span /spanspan class='line' /spanspan class='line' span class=l-Scalar-Plainitem_selector/spanspan class=p-Indicator:/span span class=l-Scalar-Plain/rss/channel/item/span /spanspan class='line' span class=l-Scalar-Plainfields/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainguid/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainGUID/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-Plainguid/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintitle/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainItem Title/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintitle/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpub_date/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=s#39;Publication/spanspan class=nv /spanspan class=sdate#39;/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-PlainpubDate/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainlink/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=s#39;Origin/spanspan class=nv /spanspan class=slink#39;/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-Plainlink/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsummary/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainSummary/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=s#39;itunes:summary#39;/span /spanspan class='line' /spanspan class='line' span class=l-Scalar-Plainids/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainguid/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaintype/spanspan class=p-Indicator:/span span class=l-Scalar-Plainstring/span /span/code/pre/td/tr/table/div/figure pThis is the one that intimidates most people: itrsquo;s where you describe the RSS source. Migrate module is even more flexible than Feeds was, so therersquo;s a lot to specify herehellip; but it all makes sense if you take it in small pieces./p pFirst: we want to use a remote file, so wersquo;ll use the Url plugin (there are others, but none that we care about right now). All the rest of the settings belong to the Url plugin, even though they arenrsquo;t indented or anything./p pThere are two possibilities for Urlrsquo;s data_fetcher setting: file and http. codefile/code is for anything you could pass to PHPrsquo;s a href=https://secure.php.net/manual/en/function.file-get-contents.phpfile_get_contents/a, including remote URLs. There are some great performance tricks in there, so itrsquo;s a good option for most use cases. Wersquo;ll be using codefile/code for our example. codehttp/code is specifically for remote files accessed over HTTP, and lets you use the full power of the HTTP spec to get your file. Think authentication headers, cache rules, etc./p pNext we declare which plugin will read (parse) the data from that remote URL. We can read JSON, SOAP, arbitrary XMLhellip; in our use case this is an RSS feed, so wersquo;ll use one of the XML plugins. SimpleXML is just what it sounds like: a simple way to get data out of XML. In extreme use cases you might use XML instead, but I havenrsquo;t encountered that yet (ever, anywhere, in any of my projects). TL;DR: SimpleXML is great. Use it./p pThird, we have to tell the source where it can find the actual items to import. XML is freeform, so therersquo;s no way for Migrate to know where the future ldquo;nodesrdquo; are in the document. So you have to give it the XPath to the items. RSS feeds have a standardized path: code/rss/channel/item/code./p pNext we have to identify the ldquo;fieldsrdquo; in the source. You see, migrate module is built around the idea that yoursquo;ll map source fields to destination fields. Thatrsquo;s core to how it thinks about the whole process. Since XML (and by extension RSS) is an unstructured format ndash; it doesnrsquo;t think of itself as having ldquo;fieldsrdquo; at all. So wersquo;ll have to give our source plugin XPaths for the data we want out of the feed, assigning each path to a virtual ldquo;fieldrdquo;. These ldquo;fake fieldsrdquo; let Migrate treat this source just like any other./p pIf you havenrsquo;t worked with XPaths before, the example YAML in this post gives you most of what you need to know. Itrsquo;s just a simple text system for specifying a tag within an unstructured XML document. Not too complicated when you get into it. You may want to a href=https://duckduckgo.com/?q=xpath+basicsfind a good tutorial/a to learn some of the tricks./p pLetrsquo;s look at one of these ldquo;fake fieldsrdquo;:/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span /pre/tdtd class='code'precode class='yaml'span class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsummary/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainSummary/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=s#39;itunes:summary#39;/span /span/code/pre/td/tr/table/div/figure pemname/em is how wersquo;ll address this field in the rest of the migration. Itrsquo;s the source ldquo;field namerdquo;. emlabel/em is the human readable name for the field. emselector/em is the XPath inside the item. Most items are flat ndash; certainly in RSS ndash; so itrsquo;s basically just the tag that surrounds the data you want. There, was that so hard?/p pAs a side note, you can see that my RSS feeds tend to be for iTunes. Sometimes the world eats an apple, sometimes an apple eats the world. Buy me a beer at Drupalcon and we can argue about standards./p pFifth and finally, we identify which ldquo;fieldrdquo; in the source contains a unique identifier. Migrate module keeps track of the association between the source and destination objects, so it can handle updates, rollbacks, and more. The example YAML relies on the very common (but technically optional) codelt;guidgt;/code tag as a unique identifier./p pstrongDestination/strong/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plaindestination/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=s#39;entity:node#39;/span /span/code/pre/td/tr/table/div/figure pYep, itrsquo;s that simple. This is where you declare what Drupal entity type will receive the data. Actually, you could write any sort of destination plugin for this ndash; if you want Drupal to migrate data into some crazy exotic system, you can do it! But in 99.9% of cases yoursquo;re migrating into Drupal entities, so yoursquo;ll want codeentity:something/code here. Donrsquo;t worry about bundles (content types) here; thatrsquo;s something we take care of in field mapping./p pstrongProcess/strong/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span span class='line-number'5/span span class='line-number'6/span span class='line-number'7/span span class='line-number'8/span span class='line-number'9/span span class='line-number'10/span span class='line-number'11/span span class='line-number'12/span span class='line-number'13/span span class='line-number'14/span span class='line-number'15/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plainprocess/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaintitle/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintitle/span /spanspan class='line' span class=l-Scalar-Plainfield_remote_url/spanspan class=p-Indicator:/span span class=l-Scalar-Plainlink/span /spanspan class='line' span class=l-Scalar-Plainbody/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsummary/span /spanspan class='line' span class=l-Scalar-Plaincreated/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainformat_date/span /spanspan class='line' span class=l-Scalar-Plainfrom_format/spanspan class=p-Indicator:/span span class=s#39;D,/spanspan class=nv /spanspan class=sd/spanspan class=nv /spanspan class=sM/spanspan class=nv /spanspan class=sY/spanspan class=nv /spanspan class=sH:i:s/spanspan class=nv /spanspan class=sO#39;/span /spanspan class='line' span class=l-Scalar-Plainto_format/spanspan class=p-Indicator:/span span class=s#39;U#39;/span /spanspan class='line' span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpub_date/span /spanspan class='line' span class=l-Scalar-Plainstatus/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plaindefault_value/span /spanspan class='line' span class=l-Scalar-Plaindefault_value/spanspan class=p-Indicator:/span span class=l-Scalar-Plain1/span /spanspan class='line' span class=l-Scalar-Plaintype/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plaindefault_value/span /spanspan class='line' span class=l-Scalar-Plaindefault_value/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpodcast_episode/span /span/code/pre/td/tr/table/div/figure pThis is where the action happens: the process section describes how destination fields should get their data from the source. Itrsquo;s the ldquo;field mappingrdquo;, and more. Each key is a destination field, each value describes where the data comes from./p pIf you donrsquo;t want to migrate the whole field exactly as itrsquo;s presented in the source, you can put individual fields through a href=https://www.drupal.org/docs/8/api/migrate-api/migrate-process-pluginsMigrate plugins/a. These plugins apply all sorts of changes to the source content, to get it into the shape Drupal needs for a field value. If you want to take a substring from the source, explode it into an array, extract one array value and make sure itrsquo;s a valid Drupal machine name, you can do that here. I wonrsquo;t do it in my example because that sort of thing isnrsquo;t common for RSS feeds, but itrsquo;s definitely possible./p pThe examples of plugins that you see here are simple ones. codestatus/code and codetype/code show you how to set a fixed field value. There are other ways, but the codedefault_value/code plugin is the best way to keep your sanity./p pThe codecreated/code field is a bit more interesting. The Drupal field is a unix timestamp of the time a node was authored. The source RSS uses a string time format, though. Wersquo;ll use the codeformat_date/code plugin to convert between the two. Neat, eh?/p pDonrsquo;t forget to map values into Drupalrsquo;s codestatus/code and codetype/code fields! codetype/code is especially important: thatrsquo;s what determines the content type, and nodes canrsquo;t be saved without it!/p h2Thatrsquo;s it?/h2 pYes, thatrsquo;s it. You now have a migrator that pulls from any kind of remote source, and creates Drupal entities out of the items it finds. Your system cron entry makes sure this runs on a regular schedule, rather than overloading Drupalrsquo;s cron./p pMore importantly, if yoursquo;re this comfortable with Migrate module, yoursquo;ve just gained a emlot/em of new power. This is a framework for getting data from anywhere, to anywhere, with a lot of convenience functionality in between./p pHappy feeding!/p h2Tips and tricks/h2 pOK I lied, there is way more to say about Migrate. Itrsquo;s a wonderful, extensible framework, and that means there are lots of options for you. Here are some of the obstacles and solutions Irsquo;ve found helpful./p pstrongImporting files/strong/p pDid you notice that I didnrsquo;t map the images into Drupal fields in my example? Thatrsquo;s because itrsquo;s a bit confusing. We actually have an image URL that we need to download, then we have to create a file entity based on the downloaded file, and then we add the File ID to the nodersquo;s field as a value. Thatrsquo;s more complicated than I wanted to get into in the general example./p pTo do this, we have to create a pipeline of plugins that will operate in sequence, to create the value we want to stick in our field_image. It looks something like this:/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span span class='line-number'5/span span class='line-number'6/span span class='line-number'7/span span class='line-number'8/span span class='line-number'9/span /pre/tdtd class='code'precode class='yaml'span class='line' span class=l-Scalar-Plainfield_image/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plaindownload/span /spanspan class='line' span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span span class=l-Scalar-Plainimage/span /spanspan class='line' span class=p-Indicator-/span span class=l-Scalar-Plainconstants/destination_uri/span /spanspan class='line' span class=l-Scalar-Plainrename/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintrue/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainentity_generate/span /span/code/pre/td/tr/table/div/figure pLooking at that download plugin, emimage/em seems clear. Thatrsquo;s the source URL we got out of the RSS feed. But what is emconstants/destination_uri/em, I hear you cry? Irsquo;m glad you asked. Itrsquo;s a constant, which I added in the source section and didnrsquo;t tell you about. You can add any arbitrary keys to the source section, and theyrsquo;ll be available like this in processing. It is good practice to lump all your constants together into one key, to keep the namespace clean. This is what it looks like:/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plain... usual source stuff here .../span /spanspan class='line' span class=l-Scalar-Plainconstants/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaindestination_uri/spanspan class=p-Indicator:/span span class=s#39;public://my_rss_feed/post.jpg#39;/span /span/code/pre/td/tr/table/div/figure pBefore you ask, yes this is exactly the same as using the codedefault_value/code plugin. Still, codedefault_value/code is preferred for readability wherever possible. In this case it isnrsquo;t really possible./p pAlso, note that the download plugin lets me set coderename: true/code. This means that in case of a name conflict, a em0, /em1, em2, /em3 etc will be added to the end of the filename./p pYou can see the whole structure here, of one plugin passing its result to the next. You can chain unlimited plugins together this wayhellip;/p pstrongMultiple interrelated migrations/strong/p pOne of the coolest tricks that Migrate can do is to manage interdependencies between migrations. Maybe you donrsquo;t want those images just as File entities, you actually want them in Paragraphs, which should appear in the imported node. Easy-peasy./p pFirst, you have to create a second migration for the Paragraph. Technically you should have a separate Migration YAML for each destination entity type. (yes, codeentity_generate/code is a dirty way to get around it, use it sparingly). So we create our second migration just for the paragraph, like this:/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span span class='line-number'5/span span class='line-number'6/span span class='line-number'7/span span class='line-number'8/span span class='line-number'9/span span class='line-number'10/span span class='line-number'11/span span class='line-number'12/span span class='line-number'13/span span class='line-number'14/span span class='line-number'15/span span class='line-number'16/span span class='line-number'17/span span class='line-number'18/span span class='line-number'19/span span class='line-number'20/span span class='line-number'21/span span class='line-number'22/span span class='line-number'23/span span class='line-number'24/span span class='line-number'25/span span class='line-number'26/span span class='line-number'27/span span class='line-number'28/span span class='line-number'29/span span class='line-number'30/span span class='line-number'31/span span class='line-number'32/span span class='line-number'33/span span class='line-number'34/span span class='line-number'35/span span class='line-number'36/span span class='line-number'37/span span class='line-number'38/span span class='line-number'39/span span class='line-number'40/span span class='line-number'41/span span class='line-number'42/span span class='line-number'43/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plainid/spanspan class=p-Indicator:/span span class=l-Scalar-Plainmy_rss_images_importer/span /spanspan class='line'span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=s#39;Import/spanspan class=nv /spanspan class=sthe/spanspan class=nv /spanspan class=simages/spanspan class=nv /spanspan class=sfrom/spanspan class=nv /spanspan class=smy/spanspan class=nv /spanspan class=sRSS/spanspan class=nv /spanspan class=sfeed#39;/span /spanspan class='line'span class=l-Scalar-Plainstatus/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintrue/span /spanspan class='line' /spanspan class='line'span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainurl/span /spanspan class='line' span class=l-Scalar-Plaindata_fetcher_plugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainhttp/span /spanspan class='line' span class=l-Scalar-Plainurls/spanspan class=p-Indicator:/span span class=s#39;https://example.com/feed.rss#39;/span /spanspan class='line' span class=l-Scalar-Plaindata_parser_plugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainsimple_xml/span /spanspan class='line' /spanspan class='line' span class=l-Scalar-Plainitem_selector/spanspan class=p-Indicator:/span span class=l-Scalar-Plain/rss/channel/item/span /spanspan class='line' span class=l-Scalar-Plainfields/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainguid/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainGUID/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=l-Scalar-Plainguid/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainname/spanspan class=p-Indicator:/span span class=l-Scalar-Plainimage/span /spanspan class='line' span class=l-Scalar-Plainlabel/spanspan class=p-Indicator:/span span class=l-Scalar-PlainImage/span /spanspan class='line' span class=l-Scalar-Plainselector/spanspan class=p-Indicator:/span span class=s#39;itunes:image[/spanspan class=se#39;#39;/spanspan class=shref/spanspan class=se#39;#39;/spanspan class=s]#39;/span /spanspan class='line' /spanspan class='line' span class=l-Scalar-Plainids/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainguid/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaintype/spanspan class=p-Indicator:/span span class=l-Scalar-Plainstring/span /spanspan class='line' span class=l-Scalar-Plainconstants/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaindestination_uri/spanspan class=p-Indicator:/span span class=s#39;public://my_rss_feed/post.jpg#39;/span /spanspan class='line' /spanspan class='line'span class=l-Scalar-Plaindestination/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=s#39;entity:paragraph#39;/span /spanspan class='line' /spanspan class='line'span class=l-Scalar-Plainprocess/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plaintype/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plaindefault_value/span /spanspan class='line' span class=l-Scalar-Plaindefault_value/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpodcast_image/span /spanspan class='line' span class=l-Scalar-Plainfield_image/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plaindownload/span /spanspan class='line' span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span span class=l-Scalar-Plainimage/span /spanspan class='line' span class=p-Indicator-/span span class=l-Scalar-Plainconstants/destination_uri/span /spanspan class='line' span class=l-Scalar-Plainrename/spanspan class=p-Indicator:/span span class=l-Scalar-Plaintrue/span /spanspan class='line' span class=p-Indicator-/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainentity_generate/span /span/code/pre/td/tr/table/div/figure pIf you look at that closely, yoursquo;ll see itrsquo;s a simpler version of the node migration we did at first. I did the copy pasting myself! Here are the differences:/p ul liDifferent ID and label (duh)/li liWe only care about two ldquo;fieldsrdquo; on the source: GUID and the image URL./li liThe destination is a paragraph instead of a node./li liWersquo;re doing the image trick I just mentioned./li /ul pNow, in the node migration, we can add our paragraphs field to the ldquo;processrdquo; section like this:/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span /pre/tdtd class='code'precode class='yaml'span class='line' span class=l-Scalar-Plainfield_paragraphs/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainmigration_lookup/span /spanspan class='line' span class=l-Scalar-Plainmigration/spanspan class=p-Indicator:/span span class=l-Scalar-Plainmy_rss_images_importer/span /spanspan class='line' span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span span class=l-Scalar-Plainguid/span /span/code/pre/td/tr/table/div/figure pWersquo;re using the codemigration_lookup/code plugin. This plugin takes the value of the field given in codesource/code, and looks it up in codemy_rss_images_importer/code to see if anything with that source ID was migrated. Remember where we configured the source plugin to know that codeguid/code was the unique identifier for each item in this feed? That comes in handy here./p pSo we pass the guid to codemigration_lookup/code, and it returns the id of the paragraph which was created for that guid. It finds out what Drupal entity ID corresponds to that source ID, and returns the Drupal entity ID to use as a field value. You can use this trick to associate content migrated from separate feeds, totally separate data sources, or whatever./p pYou should also add a dependency on codemy_rss_images_importer/code at the bottom of your YAML file, like this:/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span /pre/tdtd class='code'precode class='yaml'span class='line'span class=l-Scalar-Plainmigration_dependencies/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainrequired/spanspan class=p-Indicator:/span /spanspan class='line' span class=p-Indicator-/span span class=l-Scalar-Plainmy_rss_images_importer/span /span/code/pre/td/tr/table/div/figure pThis will ensure that codemy_rss_images_importer/code will always run before codemy_rss_importer/code./p p(NB: in Drupal lt; 8.3, this plugin is called codemigration/code)/p pstrongFormatting dates/strong/p pVery often you will receive dates in a format other than what Drupal wants to accept as a valid field value. In this case the codeformat_date/code process plugin comes in very handy, like this:/p figure class='code'figcaptionspan/span/figcaptiondiv class=highlighttabletrtd class=gutterpre class=line-numbersspan class='line-number'1/span span class='line-number'2/span span class='line-number'3/span span class='line-number'4/span span class='line-number'5/span /pre/tdtd class='code'precode class='yaml'span class='line' span class=l-Scalar-Plainfield_published_date/spanspan class=p-Indicator:/span /spanspan class='line' span class=l-Scalar-Plainplugin/spanspan class=p-Indicator:/span span class=l-Scalar-Plainformat_date/span /spanspan class='line' span class=l-Scalar-Plainfrom_format/spanspan class=p-Indicator:/span span class=s#39;D,/spanspan class=nv /spanspan class=sd/spanspan class=nv /spanspan class=sM/spanspan class=nv /spanspan class=sY/spanspan class=nv /spanspan class=sH:i:s/spanspan class=nv /spanspan class=sO#39;/span /spanspan class='line' span class=l-Scalar-Plainto_format/spanspan class=p-Indicator:/span span class=s#39;Y-m-d\TH:i:s#39;/span /spanspan class='line' span class=l-Scalar-Plainsource/spanspan class=p-Indicator:/span span class=l-Scalar-Plainpub_date/span /span/code/pre/td/tr/table/div/figure pThis one is pretty self-explanatory: from format, to format, and source. This is important when migrating from Drupal 6, whose date fields store dates differently from 8. Itrsquo;s also sometimes handy for RSS feeds. :)/p pstrongDrush commands/strong/p pVery important for testing, and the whole reason we have codemigrate_plus/code module installed! Here are some handy drush commands for interacting with your migration:/p ul licodedrush ms/code: Gives you the status of all known migrations. How many items are there to import? How many have been imported? Is the import running?/li licodedrush migrate-rollback/code: Rolls back one or more migrations, deleting all the imported content./li licodedrush migrate-messages/code: Get logged messages for a particular migration./li licodedrush mi/code: Runs a migration. use code--all/code to run them all. Donrsquo;t worry, Migrate will sort out any dependencies yoursquo;ve declared and run them in the right order. Also worth noting: code--limit=10/code does a limited run of 10 items, and code--feedback=10/code gives you an in-progress status line every 10 items (otherwise you get nothing until itrsquo;s finished!)./li /ul pOkay, now thatrsquo;s really it. Happy feeding!/p pimg class=center src=http://ohthehugemanatee.github.io/images/feed-me-seymour.gif title=#34;Feed me, Seymour!#34; alt=#34;Feed me, Seymour!#34;/p

Hook 42: Accessibility and Drupal Meetup

Wed, 06/07/2017 - 03:22
div class=image div class=field-items class=field-items div class=field-item even rel=og:image rdfs:seeAlso resource=http://www.hook42.com/sites/default/files/styles/image_style_blog_list/public/field/image/hook-42-accessibility-drupal-meetup-mike-gifford.png?itok=6sT5dCSY class=field-item evenimg typeof=foaf:Image src=http://www.hook42.com/sites/default/files/styles/image_style_blog_list/public/field/image/hook-42-accessibility-drupal-meetup-mike-gifford.png?itok=6sT5dCSY width=466 height=220 alt=Hook 42#039;s Accessibility and Drupal Meetup with Mike Gifford title=Hook 42#039;s Accessibility and Drupal Meetup with Mike Gifford //div /div /div div class=field field-name-body field-type-text-with-summary field-label-hidden field-wrapper body field div class=field-items class=field-items div class=field-item even property=content:encoded class=field-item evenpThe power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect.br - Tim Berners-Lee, W3C Director and inventor of the World Wide Webbr br As a community, Drupal wants to be sure that the websites and the features we build are accessible to everyone, including those who have disabilities. To be inclusive we must think beyond color contrasts, font scaling, and alt texts. Identifying the barriers and resolving them is fundamental in making the web inclusive for everyone.br br Accessibility fosters social equality and inclusion for not just those with disabilities but also those with intermittent internet access in rural communities and developing nations./p pThe Bay Area is fortunate to have a href=https://www.drupal.org/u/mgiffordMike Gifford/anbsp;visiting from Canada and he carries with him unique perspectives on web accessibility. Hook 42 has organized an evening with Mike for conversation, collaboration, and thought leadership surrounding a href=https://www.drupal.org/about/features/accessibilityDrupal Accessibility/a./p /div /div /div

TimOnWeb.com: Add reCaptcha to your Drupal 7 forms programatically

Wed, 06/07/2017 - 00:44
pIf you want to add Google#39;s reCaptcha (https://www.google.com/recaptcha/intro/index.html) to your Drupal 7 forms programmatically you need to follow these two steps:/p p1) Install and enable captcha (https://www.drupal.org/project/captcha) and recaptcha (https://www.drupal.org/project/recaptcha) modules. The best .../p pa href=http://timonweb.com/posts/add-recaptcha-to-your-drupal-7-forms-programatically/ class=btnRead now/a/p

Elevated Third: Acquia Showcases Headless Drupal Development for Boreal Mountain Resort

Tue, 06/06/2017 - 20:59
span class=field field--name-title field--type-string field--label-hiddenAcquia Showcases Headless Drupal Development for Boreal Mountain Resort/span emAcquia Showcases/em Headless Drupal Development for Boreal Mountain Resort span class=field field--name-uid field--type-entity-reference field--label-hidden a title=View user profile. href=https://www.elevatedthird.com/about/team/nate-gengler lang= about=https://www.elevatedthird.com/about/team/nate-gengler typeof=schema:Person property=schema:name datatype= class=username xml:lang=Nate Gengler/a/span span class=field field--name-created field--type-created field--label-hiddenTue, 06/06/2017 - 12:59/span div class=field field--name-field-image field--type-entity-reference field--label-hidden field__itemarticle class=media media-image view-mode-bannerdiv class=field field--name-field-image field--type-image field--label-hidden field__item img src=https://www.elevatedthird.com/sites/default/files/styles/hero_banner/public/image/2017-06/General%20.jpg?itok=fwEsSkYh width=1340 height=540 alt=Headless Drupal blog banner typeof=foaf:Image class=image-style-hero-banner //div /article/div div class=field field--name-body field--type-text-with-summary field--label-hidden div class=body-content p dir=ltrWe recently launched our first decoupled Drupal site for a href=https://www.elevatedthird.com/work/boreal-mountain-resortBoreal Mountain Resort/a. Working closely with hosting platform, Acquia, and front end developers, Hoorooh Digital, we spun up a href=http://www.rideboreal.com/ rel=nofollow target=_blankrideboreal.com/a as a fully customized front end experience with the back-end framework of Drupal 8./p p dir=ltrOur hosting partners, a href=https://www.acquia.com/ rel=nofollow target=_blankAcquia/a, recapped the build with a a href=https://www.acquia.com/blog/how-powdr-brings-slopes-any-screen-decoupled-drupal/01/06/2017/3304871 rel=no target=_blankfantastic blog post/a. It offers an in-depth look at the working relationship between Elevated Third, Acquia and Hoorooh Digital./p pThere is always satisfaction in retracing the progression of a project from initial discovery to final site launch. But more than an excuse to pat ourselves on the back, reflecting on projects helps us improve. It gives us a sense of how we stack up against our original goals and provides context for future builds.br / For more information on decoupled Drupal Development and other industry news, Acquia’s blog is an awesome resource. Check it out! /p p /p a href=https://www.acquia.com/blog/how-powdr-brings-slopes-any-screen-decoupled-drupal/01/06/2017/3304871 rel=nofollowimg alt=Acquia's showcase blog for Boreal Mountain's headless Drupal site data-entity-type=file data-entity-uuid=f5d66572-12f1-4452-a8ce-e0f50b1eda79 src=https://www.elevatedthird.com/sites/default/files/inline-images/Screen%20Shot%202017-06-06%20at%201.27.20%20PM.png class=align-center //a pa href=https://www.acquia.com/blog/how-powdr-brings-slopes-any-screen-decoupled-drupal/01/06/2017/3304871 rel=nofollow /a/p p /p /div /div

Droptica: Droptica: START YOUR ADVENTURE WITH DOCKER-CONSOLE IN THE EXAMPLE OF THE DRUPAL 7 PROJECT

Tue, 06/06/2017 - 15:02
docker-console init --tpl drupal7 People who follow our blog already know that we’re using Docker at Droptica. We also already told you how easy it is to start a project using our docker-drupal application (a href=https://www.droptica.pl/blog/poznaj-aplikacje-docker-drupal-w-15-minut-docker-i-przyklad-projektu-na-drupal-8/https://www.droptica.pl/blog/poznaj-aplikacje-docker-drupal-w-15-minut-docker-i-przyklad-projektu-na-drupal-8//a). Another step on the road to getting efficient and proficient with Docker is docker-console application, which is a newer version of docker-drupal, and exactly like its predecessor it was created in order to make building a working environment for Drupal simple and more efficient. How does it all work? You are going to see that in this write-up. Since we're all working on Linux (mainly on Ubuntu), all commands shown in this post were executed on Ubuntu 16.04.

ThinkShout: Fade To Black - Responsive CSS Gradients

Tue, 06/06/2017 - 14:30
pimg src=/assets/images/blog/fade-to-black-1.jpg alt=fade-to-black-1.jpg class=left forty / a href=//alistapart.com/article/responsive-web-designResponsive design/a brings a fascinating array of challenges to both designers and developers. Using background images in a call to action or blockquote element is a great way to add visual appeal to a design, as you can see in the image to the left./p pbr clear=all /br //p pimg src=/assets/images/blog/fade-to-black-2.jpg alt=fade-to-black-2.jpg class=right thirty / However, at mobile sizes, you’re faced with some tough decisions. Do you try and stretch the image to fit the height of the container? If so, at very tall/narrow widths, you’re forced to load a giant image, and it likely won’t be recognizable./p pIn addition, forcing mobile users to load a large image is bad for performance. Creating custom responsive image sets would work, but that sets up a maintenance problem, something most clients will emnot/em appreciate./p pLuckily, there’s a solution that allows us to keep the image aspect ratio, set up standard a href=//css-tricks.com/responsive-images-youre-just-changing-resolutions-use-srcset/responsive images/a, and it looks great on mobile as well. The fade-out!/p pI’ll be using screenshots and code here, but I’ve also made a href=//codepen.io/collection/XeBvKo/all 6 steps available on CodePen/a if you want to play with the code and try out different colors, images, etc…/p pbr clear=all /br //p pLet’s start with that first blockquote:/p pimg src=/assets/images/blog/fade-to-black-1.jpg alt=fade-to-black-1.jpg class=left forty / a href=//codepen.io/komejo/pen/GERJwy(pen)/a This is set up for desktop - the image aspect ratio is determining the height of the container using the a href=//stackoverflow.com/questions/1495407/maintain-the-aspect-ratio-of-a-div-with-csspadding ratio trick/a. Everything in the container is using absolute positioning and a href=http://www.sketchingwithcss.com/samplechapter/cheatsheet.htmlflexbox/a for centering. We have a simple code class=highlighter-rougergba()/code background set using the code class=highlighter-rouge:before/code pseudo-property in the .parent-container:/p div class=language-css highlighter-rougepre class=highlightcode span class=nd:before/span span class=p{/span span class=nlcontent/spanspan class=p:/span span class=s1/spanspan class=p;/span span class=nldisplay/spanspan class=p:/span span class=nbblock/spanspan class=p;/span span class=nlposition/spanspan class=p:/span span class=nbabsolute/spanspan class=p;/span span class=nlwidth/spanspan class=p:/span span class=m100%/spanspan class=p;/span span class=nlheight/spanspan class=p:/span span class=m100%/spanspan class=p;/span span class=nlbackground-color/spanspan class=p:/span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/spanspan class=m0/spanspan class=p,/spanspan class=m0/spanspan class=p,/spanspan class=m0.4/spanspan class=p);/span span class=nlz-index/spanspan class=p:/span span class=m10/spanspan class=p;/span span class=nltop/spanspan class=p:/span span class=m0/spanspan class=p;/span span class=p}/span /code/pre /div pbr clear=all /br //p pimg src=/assets/images/blog/fade-to-black-3.jpg alt=fade-to-black-3.jpg class=right forty / a href=//codepen.io/komejo/pen/QgWyLN(pen)/a The issues arise once we get a quote of reasonable length, and/or the page width gets too small. As you can see, it overflows and breaks quite badly./p pbr clear=all /br //p pimg src=/assets/images/blog/fade-to-black-4.jpg alt=fade-to-black-4.jpg class=left forty / a href=//codepen.io/komejo/pen/XgWXWz(pen)/a We can fix this by setting some changes to take place at a certain breakpoint, depending on the max length of the field and the size of the image used./p pSpecifically, we remove the padding from the parent element, and make the .content-wrapper code class=highlighter-rougeposition: static/code. (I like to set a min-height as well just in case the content is very small)/p pbr clear=all /br //p pimg src=/assets/images/blog/fade-to-black-5.jpg alt=fade-to-black-5.jpg class=right forty / a href=//codepen.io/komejo/pen/JJjGXB(pen)/a Now we can add the fader code - code class=highlighter-rougebackground-image: linear-gradient/code, which can be used a href=http://caniuse.com/#search=linear-gradientunprefixed/a. This is inserted into the .image-wrapper using another code class=highlighter-rouge:before/code pseudo-element:/p div class=language-css highlighter-rougepre class=highlightcode span class=nd:before/span span class=p{/span span class=nlcontent/spanspan class=p:/span span class=s1/spanspan class=p;/span span class=nldisplay/spanspan class=p:/span span class=ninline-block/spanspan class=p;/span span class=nlposition/spanspan class=p:/span span class=nbabsolute/spanspan class=p;/span span class=nlwidth/spanspan class=p:/span span class=m100%/spanspan class=p;/span span class=nlheight/spanspan class=p:/span span class=m100%/spanspan class=p;/span span class=nlbackground-image/spanspan class=p:/span span class=nlinear-gradient/spanspan class=p(/span span class=p///span span class=nFade/span span class=nover/span span class=nthe/span span class=nentire/span span class=nimage/span span class=n-/span span class=nnot/span span class=ngreat/spanspan class=p./span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.0/spanspan class=p)/span span class=m0%/spanspan class=p,/span span class=nrgba/spanspan class=p(/spanspan class=m255/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m1.0/spanspan class=p)/span span class=m100%/span span class=p);/span span class=p}/spanspan class=o;/span /code/pre /div pbr clear=all /br //p pimg src=/assets/images/blog/fade-to-black-6.jpg alt=fade-to-black-6.jpg class=left forty / a href=//codepen.io/komejo/pen/XgWXNZ(pen)/a The issue now is that the gradient covers the entire image, but we can fix that easily by adding additional code class=highlighter-rougergba()/code values, in effect ‘stretching’ the part of the gradient that’s transparent:/p div class=language-css highlighter-rougepre class=highlightcode span class=nd:before/span span class=p{/span span class=nlbackground-image/spanspan class=p:/span span class=nlinear-gradient/spanspan class=p(/span span class=p///span span class=nTransparent/span span class=nat/span span class=nthe/span span class=nbtop/spanspan class=p./span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.0/spanspan class=p)/span span class=m0%/spanspan class=p,/span span class=p///span span class=nStill/span span class=nbtransparent/span span class=nthrough/span span class=m70%/span span class=nof/span span class=nthe/span span class=nimage/spanspan class=p./span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.0/spanspan class=p)/span span class=m70%/spanspan class=p,/span span class=p///span span class=nNow/span span class=nfade/span span class=nto/span span class=nbsolid/span span class=nto/span span class=nmatch/span span class=nthe/span span class=nbackground/spanspan class=p./span span class=nrgba/spanspan class=p(/spanspan class=m255/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m1.0/spanspan class=p)/span span class=m100%/span span class=p);/span span class=p}/span /code/pre /div pbr clear=all /br //p pimg src=/assets/images/blog/fade-to-black-7.jpg alt=fade-to-black-7.jpg class=right forty / a href=//codepen.io/komejo/pen/RgwrZb(pen)/a Finally, we can fine-tune the gradient by adding even more code class=highlighter-rougergba()/code values and setting the percentages and opacity as appropriate./p pOnce we’re satisfied that the gradient matches the design, all that’s left is to make the gradient RGBA match the .parent-container background color (not the overlay - this tripped me up for a while!), which in our case is supposed to be code class=highlighter-rouge#000/code:/p pbr clear=all //p div class=language-css highlighter-rougepre class=highlightcode span class=nd:before/span span class=p{/span span class=nlbackground-image/spanspan class=p:/span span class=nlinear-gradient/spanspan class=p(/span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.0/spanspan class=p)/span span class=m0%/spanspan class=p,/span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.0/spanspan class=p)/span span class=m70%/spanspan class=p,/span span class=p///span span class=nThese/span span class=nthree/span span class=s2'smooth'/span span class=nout/span span class=nthe/span span class=nfade/spanspan class=p./span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.2/spanspan class=p)/span span class=m80%/spanspan class=p,/span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.7/spanspan class=p)/span span class=m90%/spanspan class=p,/span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0.9/spanspan class=p)/span span class=m95%/spanspan class=p,/span span class=p///span span class=nSolid/span span class=nto/span span class=nmatch/span span class=nthe/span span class=nbackground/spanspan class=p./span span class=nrgba/spanspan class=p(/spanspan class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m0/spanspan class=p,/span span class=m1.0/spanspan class=p)/span span class=m100%/span span class=p);/span span class=p}/span /code/pre /div pWe’ll be rolling out sites in a few weeks with these techniques in live code, and with several slight variations to the implementation (mostly adding responsive images and making allowances for Drupal’s markup), but this is the core idea used./p pFeel free to a href=//codepen.io/collection/XeBvKo/play with the code/a yourself, and change the code class=highlighter-rougergba()/code values so that you can see what each is doing./p

InternetDevels: Using Node.js with Drupal: the time has come for some real-time magic!

Tue, 06/06/2017 - 13:38
div class=field field--name-field-preview-image field--type-image field--label-hiddendiv class=field__itemsdiv class=field__item evenimg src=/sites/default/files/public/blog_preview/4_1.jpg width=936 height=622 alt=Використання Node.js із Drupal: магія в реальному часі //div/div/divdiv class=field field--name-body field--type-text-with-summary field--label-hiddendiv class=field__itemsdiv class=field__item evenpThere is a real “elixir of vivacity” that can help your Drupal website or app come alive in a way it never has. Sound lucrative? You’ll discover the rest from today’s story. After a glimpse at a href=https://internetdevels.com/blog/drupal-angular-js-web-app-development target=_blankcombining Drupal with AngularJS/a, we are now moving on to another member of the JavaScript family that is rapidly gaining popularity — Node.js. Let’s discover the reasons for its recognition, the benefits of using Node.js with Drupal, and the tool that helps you bring them together./p a href=https://internetdevels.com/blog/node-js-and-drupalRead more/a/div/div/div

Agiledrop.com Blog: AGILEDROP: Top Drupal Blogs from May

Tue, 06/06/2017 - 08:29
a href=http://www.agiledrop.com/blog/top-drupal-blogs-mayimg src=https://www.agiledrop.com/sites/default/files/2017-06/tulips-2339484_640.jpg //a We hope you are informed as much as possible about Drupal things. We are trying to deliver them to you as much as possible. One of the ways is by looking at the best work from other authors from the past month. Therefore, here are the best Drupal blogs from May. We will start our list with Improvements and changes in Commerce 2.x by Sascha Grossenbacher. In this blog post, the author focuses on explaining some of the key differences in the new version of Drupal Commerce and how they affect developers and users. Our second choice is What makes DrupalCon different? from Dagny Evans. She… a href=http://www.agiledrop.com/blog/top-drupal-blogs-mayREAD MORE/a

Freelock : Added D8 Rules support to Matrix API

Mon, 06/05/2017 - 19:01
div class=g-plusone-wrapper style=margin: 0 1em 1em 1em;float:right g:plusone href=https://www.freelock.com/blog/john-locke/2017-06/added-d8-rules-support-matrix-api size=medium annotation=bubble width=250 /g:plusone/divdiv class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item evenpAs of today, the Drupal a href=https://www.drupal.org/project/matrix_apiMatrix API/a module now supports sending messages to a room via a href=https://www.drupal.org/project/rulesRules/a. Now you can automatically configure notifications to Matrix rooms without touching any code!/p pThis is useful if you want to get notified in a Matrix room of some event on your website, such as a new comment, a user registration, updated content, etc./p pRules is still in Alpha, and has some UI quirks, but it works fine./p/div/div/divdiv class=field field-name-taxonomy-vocabulary-5 field-type-taxonomy-term-reference field-label-hiddendiv class=field-itemsdiv class=field-item evena href=/tag/drupalDrupal/a/divdiv class=field-item odda href=/tag/matrixMatrix/a/divdiv class=field-item evena href=/tag/drupal-8Drupal 8/a/divdiv class=field-item odda href=/tag/drupal-planetDrupal Planet/a/divdiv class=field-item evena href=/tag/integrationIntegration/a/div/div/div

Web Omelette: Dynamic menu links in Drupal 8 with plugin derivatives

Mon, 06/05/2017 - 17:35
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item evenpDrupal 8 has become much more flexible for doing pretty much everything. In this article I want to talk a bit about menu links and show you how powerful the new system is compared to Drupal 7./p pIn Drupal 7, menu links were a thing of their own with an API that you can use to create them programatically and put them in a menu. So if you wanted to deploy a menu link in code, you’d have to write an update hook and create the link programatically. All in a day’s…/p pWe have much more control in Drupal 8. First, it has become significantly easier to do the same thing. Menu links are now plugins discovered from YAML files. So for example, to define a link in code, all you need is place the following inside a codemy_module.links.menu.yml/code file:/p pre class=brush: php my_module.link_name: title: 'This is my link' description: 'See some stuff on this page.' route_name: my_module.route_it_points_to parent: my_module.optional_parent_link_name_it_belongs_under menu_name: the_menu_name_we_want_it_in weight: -1 /prepAnd that’s it. If you specify a parent link which is in a menu, you no longer even need to specify the menu name. So clearing the cache will get this menu link created and added to your menu. And even more, removing this code will remove your menu link from the menu. With D7 you need another update hook to clear that link./p pSecond, you can do far more powerful things than this. In the example above, we know the route name and have hardcoded it there. But what if we don’t yet and have to grab it from somewhere dynamically. That is where plugin derivatives come into play. For more information about what these are and how they work, do check out my a href=https://www.sitepoint.com/tutorial-on-using-drupal-8-plugin-derivatives-effectively/previous article/a on the matter./p pSo let’s see an example of how we can define menu links dynamically. First, let’s head back to our code*.links.menu.yml/code file and add our derivative declaration and then explain what we are doing:/p pre class=brush: php my_module.product_link: class: Drupal\my_module\Plugin\Menu\ProductMenuLink deriver: Drupal\my_module\Plugin\Derivative\ProductMenuLink menu_name: product /prepFirst of all, we want to create dynamically a menu link inside the codeproduct/code menu for all the products on our site. Let’s say those are entities./p pThere are two main things we need to define for our dynamic menu links: the class they use and the deriver class responsible for creating a menu link derivative for each product. Additionally, we can add here in the YAML file all the static information that will be common for all these links. In this case, the menu name they’ll be in is the same for all we might as well just add it here./p pNext, we need to write those two classes. The first would typically go in the codePlugin/Menu/code namespace of our module and can look as simple as this:/p pre class=brush: php namespace Drupal\my_module\Plugin\Menu; use Drupal\Core\Menu\MenuLinkDefault; /** * Represents a menu link for a single Product. */ class ProductMenuLink extends MenuLinkDefault {} /prepWe don’t even need to have any specific functionality in our class if we don’t need it. We can extend the codeMenuLinkDefault/code class which will contain all that is needed for the default interaction with menu links — and more important, implement the codeMenuLinkInterface/code which is required. But if we need to work with these programatically a lot, we can add some helper methods to access plugin information./p pNext, we can write our deriver class that goes in the codePlugin/Derivative/code namespace of our module:/p pre class=brush: php lt;?php namespace Drupal\my_module\Plugin\Derivative; use Drupal\Component\Plugin\Derivative\DeriverBase; use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Derivative class that provides the menu links for the Products. */ class ProductMenuLink extends DeriverBase implements ContainerDeriverInterface { /** * @var EntityTypeManagerInterface $entityTypeManager. */ protected $entityTypeManager; /** * Creates a ProductMenuLink instance. * * @param $base_plugin_id * @param EntityTypeManagerInterface $entity_type_manager */ public function __construct($base_plugin_id, EntityTypeManagerInterface $entity_type_manager) { $this-gt;entityTypeManager = $entity_type_manager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, $base_plugin_id) { return new static( $base_plugin_id, $container-gt;get('entity_type.manager') ); } /** * {@inheritdoc} */ public function getDerivativeDefinitions($base_plugin_definition) { $links = []; // We assume we don't have too many... $products = $this-gt;entityTypeManager-gt;getStorage('product')-gt;loadMultiple(); foreach ($products as $id =gt; $product) { $links[$id] = [ 'title' =gt; $product-gt;label(), 'route_name' =gt; $product-gt;toUrl()-gt;getRouteName(), 'route_parameters' =gt; ['product' =gt; $product-gt;id()] ] + $base_plugin_definition; } return $links; } } /prepThis is where most of the logic happens. First, we implement the codeContainerDeriverInterface/code so that we can expose this class to the container and inject the Entity Type Manager. You can see the codecreate()/code method signature is a bit different than you are used to. Second, we implement the codegetDerivativeDefinitions()/code method to return an array of plugin definitions based on the master definition (the one found in the YAML file). To this end, we load all our products and create the array of definitions./p pSome things to note about this array of definitions. The keys of this array are the ID of the derivative, which in our case will match the Product IDs. However, the menu link IDs themselves will be made up of the following construct code[my_module].product_link:[product-id]/code. That is the name of the link we set in the YAML file + the derivative ID, separated by a colon./p pThe route name we add to the derivative is the canonical route of the product entity. And because this route is dynamic (has arguments) we absolutely must also have the coderoute_parameters/code key where we add the necessary parameters for building this route. Had the route been static, no route params would have been necessary./p pFinally, each definition is made up of what we specify here + the base plugin definition for the link (which actually includes also all the things we added in the YAML file). If we need to interact programatically with these links and read some basic information about the products themselves, we can use the codeoptions/code key and store that data. This can then be read by helper methods in the codeDrupal\my_module\Plugin\Menu\ProductMenuLink/code class./p pAnd that’s it. Now if we clear the cache, all our products are in the menu. If we create another product, it’s getting added to the menu (once the caches are cleared)./p h2Bonus/h2 pYou know how you can define action links and local tasks (tabs) in the same way as menu link? In their respective YAML files? Well the same applies for the derivatives. So using this same technique, you can define local actions and tasks dynamically. The difference is that you will have a different class to extend for representing the links. For local tasks it is codeLocalTaskDefault/code and for local actions it is codeLocalActionDefault/code./p h2Summary/h2 pIn this article we saw how we can dynamically create menu links in Drupal 8 using derivatives. In doing so, we also got a brief refresher on how derivatives work. This is a very powerful subsystem of the Plugin API which hides a lot of powerful functionality. You just gotta dig it out and use it./p /div/div/div

heykarthikwithu: Drupal 7 - Apache Solr Search, How to setup and how to index?

Mon, 06/05/2017 - 09:55
spanDrupal 7 - Apache Solr Search, How to setup and how to index?/span divpInstall Solr on the machine, Setup the Core, Install and Configure the Apache Solr Search module and do the Indexing../p /div spanspan lang= about=http://dev-karthikkumardk.pantheonsite.io/user/1 typeof=schema:Person property=schema:name datatype= xml:lang=heykarthikwithu/span/span spanMon, 06/05/2017 - 13:25/span