drupal.org - aggregated feeds in category Drupal Planet
Updated: 3 hours 8 min ago
Thu, 05/16/2013 - 23:40
div class=field field-name-body field-type-text-with-summary field-label-hidden view-mode-teaserdiv class=field-itemsdiv class=field-item even property=content:encoded It can be tough sometimes for web developers. That beautiful/exciting/inspiring new site that’s almost ready to launch looks great and works well in all browsers… except for Internet Explorer. Menus don’t align properly, rounded corners disappear, images don’t quite fit the same… It’s a continual challenge to help IE fit in with the big boys Firefox, Chrome and Safari. /div/div/div
Thu, 05/16/2013 - 21:11
pThe idea for this series of posts started at lunch one day when I made an off-hand comment about reading Hex numbers and making fast changes in my CSS file. I am somewhat new to developing for Drupal, but amid all the new information and terminology was something familiar, colour-space*. A sword that I understood how to put to use in elegant arcs within the rest of the coding I was learning./p
pa href=http://redfinsolutions.com/blog/introduction-series-posts-colour target=_blankread more/a/p
Thu, 05/16/2013 - 20:50
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item evenpPrepaid ticket holders, sponsors with unredeemed coupon codes, and any unregistered person looking to not pay the onsite price to attend DrupalCon have just over 24 hours to register before online registration closes this Friday, May 17 at 5:00pm PDT. /p/div/div/div
Thu, 05/16/2013 - 20:16
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even pI saw this tweet flashing by in my stream today:/p
pimg height=96 width=457 alt=Drupaleros title=Drupaleros class=media-element file-media-original content-image-center content-image-shadow src=http://www.tsvenson.com/files/media/blog/drupaleros.png //p
pWhat immediately caught my eye was strongDrupaleros/strong, the Spanish word for Drupal User. Its such a great word and just sounds great./p
pOr what do you say about:/p
blockquote
pWe are the Drupaleros!/p
/blockquote
pAwesome isn't it?/p
pEven better, if you know your Spanish it is unisex too./p
pHow about adopting it as the official name for us who are passionate about Drupal?/p
pLets all be Drupaleros!/p /div/div/divdiv class=field field-name-field-link-to-self-for-rss field-type-link-field field-label-hiddendiv class=field-itemsdiv class=field-item evena href=http://www.tsvenson.com/blog/2013/05/we-are-the-drupaleros title=We are the DrupalerosRead the full We are the Drupaleros post on www.tsvenson.com/a/div/div/div
Thu, 05/16/2013 - 20:00
pTo expand and gain a stronger foothold in the VM storage market, a href=http://www.tintri.comTintri/a turned to Chapter Three to create a new look and feel for their business. As a team, the two companies built a stronger content structure that spoke more effectively to Tintri’s primary audiences./p
pThe project was a resounding success, resulting in an immediate 30% increase in traffic and a significant uptick in lead generation after just one month./p
pimg src=/sites/default/files/Tintri-BeforeAfter.png border=0 width=550 height=603 //p
p class=pullquote style=width: 520px;Chapter Three took us from concept to completion on time and on budget—even though we didn’t have a lot of either. Their process kept the project moving along and still met our iteration expectations. From a site maintenance standpoint, we can now do in a few minutes what used to take hours. We’re ecstatic with our new site and so are our visitors. When I hear from people that have been on the site, their first comment is usually around how easy it is to find what they’re looking for. Great work all around.br /span style=line-height: 1.538em;br /- Dave Frederick | Senior Director of Corporate Marketing/span/p
div
pnbsp;/p
h3Identifying the problem, developing the solution/h3
pTintri, a B2B specializing in VM-aware storage, wanted a new website to better solicit business from larger companies. Their existing Wordpress site looked dated, and it was not instilling confidence in larger customers. It also failed to provide enough flexibility for their communication needs.nbsp;/p
pWe solved Tintri’s problems with a two-pronged approach:/p
ol
lispan style=line-height: 1.538em;Improve the visual presentation of the site/span/li
lispan style=line-height: 1.538em;Restructure the site to serve up more relevant content/span/li
/ol
div
pnbsp;/p
h3Improving the visual design/h3
divimg src=/sites/default/files/Tintri-variations.png border=0 width=549 height=357 //div
pTintri wanted its website to convey simplicity and efficiency without unnecessary frills or adornments. The company wanted straightforward and consistent communication. Our team approached the design aesthetic from a variety of perspectives until we found the right fit./p
/div
pAs a rapidly-growing startup, Tintrí needed to have a design that could scale along with the business and support a visionary approach. By creating a full-width design, we could reinforce these company attributes with maximum real estate for strong visual messaging. nbsp;/p
divstrong style=font-weight: normal;span style=font-size: 15px; font-family: Arial; background-color: transparent; white-space: pre-wrap;img src=/sites/default/files/tintri-comp.png border=0 width=550 height=440 //span/strong/div
h3Leveraging Drupal’s strengths for content strategy/h3
pTintri’s technical audience prefers consistency and brevity over jargon and fluff. Understanding that site visitors were coming primarily for information, we built ways to showcase nine different kinds of related content on almost every page. With this approach, visitors can find what they are looking for without hunting around or use the search function. It also allows site administrators to create content once, and leverage it multiple times./p
pimg src=/sites/default/files/Tintri-related.png border=0 width=550 height=603 //p
/div
Thu, 05/16/2013 - 19:30
div class=field field-name-field-main-image field-type-image field-label-hiddendiv class=field-itemsdiv class=field-item evenimg hspace=10 align=right width=190 height=190 src=http://www.lullabot.com/sites/default/files/styles/190x190_rounded/public/entry_image/drupalizeme-200dollar_front.jpg?itok=IlAS5gO5 alt= //div/div/div
pLullabot has always had a big presence at DrupalCon and next week's event in Portland, OR is no exception. We're teaching 4 classes and presenting 11 sessions. We've got 2 booths in the expo hall. We're having a big party on Tuesday night. And nearly the entire Lullabot team will be in Portland. For the latest updates, please a href=http://twitter.com/lullabotfollow us on Twitter/a and a href=http://facebook.com/lullabotslike us on Facebook/a./p
pHere's the breakdown of where we'll be and when:/p
Thu, 05/16/2013 - 18:30
div class=field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-abovediv class=field-labelTopic:nbsp;/divdiv class=field-itemsdiv class=field-item evena href=/tag/drupal typeof=skos:Concept property=rdfs:label skos:prefLabelDrupal/a/div/div/divdiv class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even property=content:encodedpIn Drupal core, we use a href=http://drupal.org/core/thresholdsissue thresholds/a to manage technical debt. Both critical (release-blocking) and major (non-release-blocking, high-impact issues) are considered. When we have more open issues than our thresholds, we do not commit new features./p
pCurrently, we have a href=http://drupal.org/project/issues/search/drupal?version[0]=8.xamp;version[1]=7.xamp;status[0]=1amp;status[1]=8amp;status[2]=13amp;status[3]=14amp;status[4]=15amp;priorities[0]=1amp;categories[0]=bug27 critical bugs/a, a href=http://drupal.org/project/issues/search/drupal?version[0]=8.xamp;version[1]=7.xamp;status[0]=1amp;status[1]=8amp;status[2]=13amp;status[3]=14amp;status[4]=15amp;priorities[0]=1amp;categories[0]=task41 critical tasks/a, a href=http://drupal.org/project/issues/search/drupal?version[0]=8.xamp;version[1]=7.xamp;status[0]=1amp;status[1]=8amp;status[2]=13amp;status[3]=14amp;status[4]=15amp;priorities[0]=4amp;categories[0]=bug155 major bugs/a, and a href=http://drupal.org/project/issues/search/drupal?version[0]=8.xamp;version[1]=7.xamp;status[0]=1amp;status[1]=8amp;status[2]=13amp;status[3]=14amp;status[4]=15amp;priorities[0]=4amp;categories[0]=task149 major tasks/a. This is more than twice our current thresholds for critical issues, and about 50% more than our thresholds for major issues. We need your help to resolve these issues so that we can resume adding new features to Drupal 8. That would be a very exciting place to get to!/p
pThere are many ways to help, including not only programming but also updating these issues' summaries, testing the patches, and making sure the patches still apply. I encourage everyone to collaborate on major and critcal issues, and to consider making them a focus at the a href=http://portland2013.drupal.org/program/sprintsDrupalCon Portland sprints/a./p
/div/div/div
Thu, 05/16/2013 - 18:23
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even property=content:encoded pThere have been a lot of mentions that Drupal 8 is using Annotations. In this article I will dive in how Drupal uses them and how to leverage Annotations mechanism yourself./ppIn brief, annotations are blocks of comments that are parsed and used as a source of information about something. For example in Drupal 8, plugins system Annotations are used to describe plugins. They are alternatives to our TYPE_hook_info hooks and are now widely used./ppFor example:/ppcodelt;?phpbr //**br /* Defines a default processor implementation.br /*br /* Creates lightweight records from feed items.br /*br /* @Plugin(br /* id = aggregator,br /* title = @Translation(Default processor),br /* description = @Translation(Creates lightweight records from feed items.)br /* )br /*/br /class DefaultProcessor extends PluginBase implements ProcessorInterface {br /}br /?gt; /code/ppHow does this work technically?/ppFor parsing annotations Drupal uses AnnotationReader class from Doctrine. This class can retrieve annotations from classes, class methods in the following way: code lt;?phpbr /use Doctrine\Common\Annotations\AnnotationReader;br /use Doctrine\Common\Annotations\AnnotationRegistry;br /use Doctrine\Common\Reflection\StaticReflectionParser;br /br /$object = new CustomClassWithAnnotations();br /$annotation_name = 'Drupal\custom_module\Annotation\CustomAnnotation';br /br /$reader = new AnnotationReader();br /br /// Register the namespaces of classes that can be used for annotations.br /$annotation_namespaces = array(br /'Drupal\custom_module\Annotation' =gt; DRUPAL_ROOT . '/modules/custom_module/lib',br /);br /AnnotationRegistry::registerAutoloadNamespaces($annotation_namespaces);br /br /$reflection_class = new StaticReflectionClass($object);br /$annotation = $reader-gt;getClassAnnotation($reflection_class, $annotation_name);br /?gt; /code/ppIn the example above $annotation will be an object - instance of class that is registered as annotation. For example in case of:/ppcodelt;?phpbr //**br /* @CustomAnnotation(br /* property1 = value1,br /* property2 = “value2”,br /* )br /class CustomClassWithAnnotations() {br /} ?gt; /code/ppAnnotationReader will check if it understands the CustomAnnotation class and instantiates it. In order the reader to understand this annotation, we should register it with AnnotationRegistry./ppHow do we define the CustomAnnotation class? A good idea would be to inherit it from – emDrupal\Component\Annotation\Pluginem. /em/emIt will parse annotation to an array that you can access the get() method code$definition = $annotation-gt;get();/code/ppDefining a new type of annotation can be done in the following way:/ppcodelt;?phpbr /namespace Drupal\custom_module\Annotation;br /use Drupal\Component\Annotation\Plugin;br //**br /* Defines an CustomAnnotation annotation type.br /*br /* @Annotationbr /*/br /class CustomAnnotation extends Plugin {br /}br /?gt; /code/ppOf course you can skip creating a new type of annotation and use @Plugin instead./ppIn Drupal, the primary usage of annotations is in AnnotatedClassDiscovery, to discover plugins. But we can go further and apply reading annotations from class methods:/ppcodelt;?phpbr /$reflection_method = new \ReflectionMethod('CustomClassWithAnnotations', $method_name);br /$annotation = $this-gt;reader-gt;getMethodAnnotation($reflection_method, 'Drupal\custom_module\Annotation\CustomAnnotation');br /?gt; /code/ppWe can use this for example for validation of arguments or even unit testing our methods (providing a set of arguments and results to test against)./ppHope this article made it a bit clearer about annotations. If you need some help on annotations we will be glad to assist you on a href=http://facebook.com/propeople target=_blankFacebook/a or a href=http://twitter.com/propeople target=_blankTwitter/a./ppYou may also share your thoughts/comments below./ppFor further reading:br /a href=http://www.slideshare.net/stubbles/declarative-development-using-annotations-in-php rel=nofollow target=_blankDeclarative development using annotations in PHP/abr /a href=http://www.masnun.com/2012/08/12/using-annotations-in-php-with-doctrine-annotation-reader.html rel=nofollow target=_blankUsing annotations in PHP with doctrine annotation reader /abr /a href=http://drupal.org/node/1683644 rel=nofollow target=_blankUse Annotations for plugin discovery/a/p /div/div/divdiv class=control-group form-type-item form-item
label class=control-labelLanguage /label
div class=controls English
/div/div
div id=comment-wrapper/divdiv class=field field-name-field-tags field-type-taxonomy-term-reference field-label-abovediv class=field-labelTags:nbsp;/divdiv class=field-itemsdiv class=field-item evena href=/tags/drupal typeof=skos:Concept property=rdfs:label skos:prefLabel datatype=Drupal/a/divdiv class=field-item odda href=/tags/development typeof=skos:Concept property=rdfs:label skos:prefLabel datatype=Development/a/divdiv class=field-item evena href=/tags/tutorials typeof=skos:Concept property=rdfs:label skos:prefLabel datatype=Tutorials/a/div/div/divdiv class=field field-name-field-drupal-planet field-type-taxonomy-term-reference field-label-abovediv class=field-labelCheck this option to include this post in Planet Drupal aggregator:nbsp;/divdiv class=field-itemsdiv class=field-item evena href=/drupal/planet typeof=skos:Concept property=rdfs:label skos:prefLabel datatype=planet/a/div/div/div
Thu, 05/16/2013 - 18:09
div class=field field-name-body field-type-text-with-summary field-label-hidden
div class=field-items
div property=content:encoded class=field-item evenpAre you a project manager working for a company adopting Drupal? Are you new to managing Drupal projects? This course is the right one for you!/p
pThis course follows the life cycle of a Drupal project from start to finish and back again and is based on our full day a href=http://training.acquia.com/course/drupal-project-managers Drupal for Project Manager’s course/a./p/div
/div
/div
span property=dc:title content=Sign up for free Drupal for project managers - mini-course class=rdf-meta/span
Thu, 05/16/2013 - 17:00
pMentorship consulting is one of the a href=https://www.lullabot.com/what-we-domany services that Lullabot provides/a, and is something we’re known for in the Drupal community. When we work with potential clients to describe what we can do for them, it can sometimes be very difficult to explain how a consulting relationship works. This is especially true if they have never participated in consulting engagements with us or another agency./p
Thu, 05/16/2013 - 16:23
div class=field field-name-field-ankeiler field-type-text-long field-label-hidden clearfix
pTwig is Drupal's best theme engine! Tomorrow I will speak at the a href=http://drupaljam.nlDrupalJam/a about 'Twig in Drupal 8'. I will explain the pros and cons of Twig for Drupal themers, show examples of new Twig templates, explain a summary of the Twig syntax and of course do a small demo of working with Twig templates. You'll find my slides here./p
/div
div class=field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix clearfix
span class=field-labelTags:nbsp;/span
a href=/category/tags/themingtheming/a a href=/category/tags/twigTwig/a a href=/category/tags/render-arrayRender Array/a /div
Thu, 05/16/2013 - 15:43
p class=field-ns-blog-post-lead
My team has been looking into the Firefox add-on Selenium IDE as a quick and simple way to create automated tests for our Drupal sites. Selenium IDE out of the box does not support conditionals, making it hard to account for unexpected behaviour. For instance, it#039;s easy to make a test of the basic Drupal login functionality, but if the user is already logged in when running that test (a common scenario when working on a site), the test will fail. The solution to this is called Sideflow. /p
div class=field-ns-blog-post-body clearfix
div class=field-item even pimg alt=selenium_ide_login_fail.png class=media-image height=247 title=selenium_ide_login_fail.png width=466 src=http://www.wunderkraut.com/sites/wunderkraut.com/files/styles/large/public/selenium_ide_login_fail.png?itok=NYeUDsua //pdivSideflow was created by Darren DeRidder and currently extends Selenium IDE with these commands: goto/gotoLabel, label, gotoIf, while, endWhile, and push. I'm only going to use gotoIf and label in this example, but you can read about the others in a href=https://github.com/darrenderidder/sideflowthe Sideflow GitHub repo/a and in a href=http://51elliot.blogspot.se/2008/02/selenium-ide-goto.htmlthe announcement on Darren's blog/a (where you can also find a lot of general Selenium IDE tips). Also see his blog posts a href=http://51elliot.blogspot.se/2011/07/selenium-ide-sideflow-update.htmlSelenium IDE Sideflow Update 1/a and a href=http://51elliot.blogspot.se/2012/07/sideflow-update-selenium-ide-flow.htmlSelenium IDE Sideflow Update 2/a./divdiv /divdivYou might wonder why I don't just start the test with deleteAllVisibleCookies (a tip I got from a href=http://joshjustice.wordpress.com/2010/04/07/6-ways-to-make-the-most-of-selenium-ide/6 Ways to Make The Most of Selenium IDE/a), which in effect would log out the user before running the rest of the test. Well, it doesn't work with Drupal's session cookie since it's set to HttpOnly, meaning it can't be controlled by Javascript. A test that does work, however, is this:/divdiv /divdivopen | /user/divdivstoreElementPresent | //input[@id='edit-name'] | userIsLoggedOut/divdivgotoIf | ${userIsLoggedOut} == false | userIsLoggedIn/divdivwaitForElementPresent | //input[@id='edit-name'] |/divdivtype | //input[@id='edit-name'] | admin/divdivwaitForElementPresent | //input[@id='edit-pass'] |/divdivtype | //input[@id='edit-pass'] | admin/divdivwaitForElementPresent | //input[@id='edit-submit'] |/divdivclickAndWait | //input[@id='edit-submit'] |/divdivlabel | userIsLoggedIn/divdiv /divdivstoreElementPresent looks for an element, in this case the username field shown when the user is logged out, and stores a Boolean value (true or false) in the variable userIsLoggedOut. If that element isn't present we can make a qualified guess that the user is already logged in, and just skip down to the label userIsLoggedIn, ending the test./divdiv /divdivimg alt=selenium_ide_login_success.png class=media-image height=247 title=selenium_ide_login_success.png width=466 src=http://www.wunderkraut.com/sites/wunderkraut.com/files/styles/large/public/selenium_ide_login_success.png?itok=JEhRMnn0 //divdiv /divdivGreen every time!/div /div
/div
Thu, 05/16/2013 - 15:30
a href=/blog/2013/05/drupal-8-aural-interfaces-groundbreaking-accessibility-drupalcon-portland class=imagecache imagecache-blog_header imagecache-linked imagecache-blog_header_linkedimg src=http://rootwork.org/sites/default/files/imagecache/blog_header/blog/switchboard-publicdomain.jpg alt=A switchboard operator for Drupal? title=A switchboard operator for Drupal? width=720 height=328 class=imagecache imagecache-blog_header//a
pI'm a millennial, but even I remember the experience of calling the telephone operator and getting a live human to look up the number of a business or place a collect call. We have the digital means to complete lots of tasks like that today, but that doesn't mean all of our methods are equally effective for everyone./p
pimg alt=Drupal's new mobile-friendly toolbar src=http://rootwork.org/sites/default/files/mobile-friendly-toolbar.png style=margin: 0 0 1em 1em; align=right height=223 width=250Drupal 8 will be the most accessible version of Drupal yet, declare strongJ. Renée Beach/strong and strongWim Leers/strong in their a href=http://portland2013.drupal.org/node/2158Drupalcon Portland session description/a./p
pThey're both part of the a href=http://drupal.org/project/sparkSpark team/a, an initiative to improve the authoring experience in Drupal for everyone./p
pSpark is more well known for things like ia href=http://drupal.org/project/editn-place editing/a and a a href=http://drupal.org/project/navbarmobile friendly toolbar/a, which you can see at right. But from the beginning, improving the experience for everyone has been a big priority, and one of the most exciting developments is a new aural interface./p
pstrongThat's right, Drupal is getting a switchboard operator:/strong/p
p style=text-align: center;img alt=Drupal announce log showing three 'polite Drupal announcements' src=http://rootwork.org/sites/default/files/drupal-announce-log.png height=48 width=675/p
pOK, so that doesn't look emterribly/em exciting all on its own. But trust me, when you watch the videos of people interacting with Drupal 8 and having menus and selections read as they go, it's pretty cool./p
pWhen I spoke with J. Renée about Drupal 8 and the nature of working on accessibility, the passion for this work really shown through. I'm really looking forward to their session with Wim, a href=http://portland2013.drupal.org/node/2158strongDrupal Speaks: Aural user interfaces, new Drupal 8 accessibility features, on Wednesday at 10:45 AM./strong/a Hope to see you there!/p
hr
pstrongIB: What are we missing when we talk about accessibility right now?/strong/p
pJRB: I want developers to understand that accessibility is fundamental to user interface development. We tend to talk about accessibility like we talk about gender. Both have coded values. When we speak of being gendered, we are often talking about being non-male. Male is a kind of genderless base state. So is it with accessibility. When we speak of making something accessible, we tend to refer to making an interface for blind users or for users with physical capabilities that make keyboard and mouse use difficult, as examples. Visual is a kind of accessible base state./p
pWe risk othering folks for whom accessibility is an issue because as developers, in general, non-visual accessibility has not been a primary concern. I know what is is like to be othered. In some ways, highlighting otherness can be an effective way to bring focus to a problem. Eventually though, we need to resolve those issues and close the loop on the otherness. We can be other and also be equal. Now is the time for front end developers to start thinking about accessibility as a multi-modal effort. We no longer have the excuse that the tools and technologies available to us do not support efficient workflows for non-visual UI development./p
pstrongIB: Where is Drupal 8 going to do better?/strong/p
pJRB: Most importantly, we have more individual core contributors this cycle who truly believe in addressing accessibility issues. And they are all smart, wonderful people which makes working with them a pleasure!/p
pFor example, take a href=http://drupal.org/node/1811128this issue about requirement warnings during installation/a. For a sighted user, a warning during installation is immediately apparent. The missing requirement is made distinct with color contrast. For a blind user, they must traverse every cell in the table to discover a missing requirement. Would we ever impose such a burden on a sight user through the UI? No, not without grumbles in the issue queues at least. With more contributors invested in improving these types of non-visual details, we are polishing all the rough edges — the ones we see emand/em the ones we don't./p
pstrongIB: How important is context in aural interfaces?/strong/p
pJRB: Context is important to all interfaces. As front end developers we build templates that expose context in a predictable, consumable way. As a practice we have established and then refined patterns of visual expression over the past 30-plus years./p
pMetaphors grounded visual pointer displays on a virtual desktop. We talk of visual affordances in rounded, gradient-embellished, reflective buttons. a href=http://en.wikipedia.org/wiki/SkeuomorphismSkeumorphic designs/a bring our understanding of the physical world to bear on pixels and bits./p
pWhere are the metaphors in aural interface design? I know of none. To me, these interfaces are flat. The metal is bare underneath them./p
pPerhaps non-visual interfaces have one less level of abstraction to traverse. Maybe there's no need to translate language into symbol and then back into language. But that little bit of designer in me, that memory of a linguist I almost was, remembers being thunderstruck with insight reading a href=http://en.wikipedia.org/wiki/Ray_JackendoffJackendoff's/a unfurling of metaphor after I had just so recently fallen smitten with the strict generative grammar of early a href=http://en.wikipedia.org/wiki/Noam_chomsky#LinguisticsChomsky/a. Jackendoff gives us a way of understanding language that starts at basic physical dichotomies — up/down and near/far — and from there offers us a model of communication. He gives us pattern. (Early) Chomsky gave us metal. So much that we humans do starts with structure that softens with time to fit our curvy, winding nature./p
pI want to believe that the aural interfaces we have today still just the awkward first attempts to build an abstract audio interface pattern language. That non-visual interface design is still working through its a href=http://en.wikipedia.org/wiki/Structural_linguisticsstructuralist/a phase. We are still learning how to pack context into denser forms through non-visual expressions./p
pstrongIB: Will the Drupal 8 improvements have things to offer module developers?/strong/p
pJRB: In Drupal 8, we are building tools that manage a couple of the trickier components of accessibility in a browser. These are:/p
p style=margin-left: 40px;1. Outputting audio updatesbr
2. Managing tabbing in constrained workflows/p
pModule developers will be able to pass a string to a method called strongannounce/strong on the Drupal object and have that string read by a screen reader./p
pAnother method on the Drupal object called strongtabbingManager/strong will constrain tabbable elements on the page. A developer will select those elements, either through JavaScript methods or jQuery, and pass them to the tabbingManager. Tabbing is then constrained to those elements until the constraint is superseded or released. I know that must not be completely clear, but that's why we're presenting a href=http://portland2013.drupal.org/node/2158a session about aural user interfaces and how we can use these new tools to build them/a!/p
pemTop image: Public domain. Drupal images from the drupal.org issue queue and the session slides./em/p
pstrongJoin Rootwork on a href=https://twitter.com/rootworkTwitter/a, a href=https://facebook.com/rootworkFacebook/a and a href=http://slideshare.net/rootworkSlideShare/a./strong/p
pa href=http://rootwork.org/servicesLearn about Rootwork's services for nonprofits and social change./a/p
Thu, 05/16/2013 - 14:50
img src=http://www.mediacurrent.com/sites/default/files/imagecache/thumb_blog_spotlight/dcportlandblog_0.png alt= title= class=imagecache imagecache-thumb_blog_spotlight imagecache-default imagecache-thumb_blog_spotlight_default width=200 height=150 / pWith a href=http://portland2013.drupal.org/ target=_blankDrupalcon/a now only a few days away, preparations are beginning to ramp up (or maybe starting to die down, depending on how much prep work your company has already done). Drupalcon is *the* Drupal event of the year—and with more than 3,000 attendees and 50+ expert-led sessions, there’s a lot to think about before boarding that plane to Portland./p
Thu, 05/16/2013 - 14:33
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even property=content:encoded pSo you're launching a new website or replacing an old one and want to make sure everything goes smoothly? This guide will give you a run-down of everything you can check to avoid common pitfalls!/p
h2Site status/h2
pYou should always start by checking the status report (a href=http://example.com/admin/reports/statushttp://example.com/admin/reports/status/a). This page shows you all of the basic requirements for your Drupal site to run correctly./p
pAny issues will be highlighted in red and typically have a link to a configuration page or the documentation to help you resolve the problem./p
h2Scheduled tasks/h2
pDrupal 7 will run scheduled tasks (known as cron jobs) out of the box, but only when users are visiting your site./p
pThis is great for small sites which don't need much housekeeping, but if your site is a bit bigger or if you don't have visitors 24/7, you should set up a a href=http://drupal.org/croncron job/a to run periodically./p
pYou can also look at a module such as a href=http://drupal.org/project/ultimate_cronUltimate cron/a which gives you fine grained control over when each scheduled task will run./p
h2Web services/h2
pMany web services such as a href=http://drupal.org/project/mollomMollom/a or a href=http://drupal.org/project/google_analyticsGoogle analytics/a need a domain name specific API key to use./p
pIf you use any of these services on your website, you should ensure that you've registered your real domain name with the service and you've updated Drupal with your new API key./p
h2Broken links/h2
pIt can be easy when copying and pasting to accidentally link directly to a file or image on a development site./p
pThese links can often stop working or perhaps worse, may direct users away from your live site and onto the development site instead./p
pYou can use a module such as a href=http://drupal.org/project/linkcheckerLink checker/a to ensure this doesn't happen, and it is good practice to a href=http://www.seas.upenn.edu/cets/answers/auth-htpasswd.htmlpassword protect/a your development website, so that users (or more likely Google!) cannot stumble accross it./p
h2Site optimisation/h2
pThe site performance page (a href=http://example.com/admin/config/development/performancehttp://example.com/admin/config/development/performance/a) will allow you to configure a number of options to help optimise your Drupal site. This includes page caching and optimising CSS and JavaScript files./p
pSee our series on High Performance in Drupal for some expert tips - a href=http://www.microserveltd.co.uk/blogs/drupal-hosting/high-performance-drupal-part-1-give-your-site-boost name=High performance in Drupal title=High performance in Drupal Part 1: Give your site a boost id=High performance in DrupalHigh performance in Drupal Part 1: Give your site a boost/a and a href=http://www.microserveltd.co.uk/blogs/drupal-development/high-performance-drupal-part-2-lightning-fast-code name=High performance in Drupal title=High performance in Drupal Part 2: Lightning fast code id=High performance in DrupalHigh performance in Drupal Part 2: Lightning fast code/a./p
h2Development modules/h2
pDevelopment modules such as devel can often reduce your website's performance, so it's worth turning them off on your live site. You can still keep them running in your development environment if needed./p
h2User accounts/h2
pMany of us are guilty of using a common or simple password to make life easier when building a website./p
pOnce the site is live, it's worth taking the time to update any administrative accounts with a href=http://strongpasswordgenerator.com/secure passwords/a./p
pIt is also worth removing any unnecessary development accounts and content. Just in case./p
h2Error messages/h2
pBeing able to see debug messages and errors are handy when creating a site, but may scare off users once the site is live./p
pEnsure that errors and warnings are hidden by visiting the Logging and errors config page./p
h2Site information/h2
pThe site information config page holds all of the most common site information, such as the website name and email address./p
pIt's worth double checking that all of this information is correct. It could be quite embarrassing if your first newsletter arrives from a href=mailto:dev@example.comdev@example.com/a./p
p /p
pSome of these pitfalls can be avoided from the get go, if you follow a few simple principles. Check out a href=http://www.microserveltd.co.uk/meet-team?uid=6Rick Donohoe's/a blog article a href=http://www.microserveltd.co.uk/blogs/drupal-training/drupal-site-building-101Drupal site building 101/a for some handy hints and tips on this!/p
/div/div/div
Thu, 05/16/2013 - 14:14
img typeof=foaf:Image src=http://getlevelten.com/sites/default/files/styles/600x300/public/content/blog/images/sendgrid.png?itok=eVXYR-hF width=600 height=300 alt= /
pMoving Drupal website clients to cloud hosting has been great as they're able to get high performance, scalable capacity at a pretty reasonable rate. However, we have discovered when clients offer an email sign-up, the emails that are generated from the cloud-hosted Drupal website are often rejected as spam. For those clients who have chosen the Rackspace cloud, here is a step-by-step solution to the problem.... a href=/blog/chris-sloan/setting-rackspace-cloud-send-drupal-emails-sendgrid class=more-linkRead more/a/p
Thu, 05/16/2013 - 13:19
div class=field field-name-field-inlineimage field-type-image field-label-hidden
a href=/sv/node/158img src=http://www.sthlmconnection.se/sites/default/files/styles/blog_teaser_4-col/public/drupal-vs-wordpress.jpg?itok=uyoVfhl9 width=300 height=175 alt= //a /div
div class=field field-name-field-teaser field-type-text-long field-label-hidden
pThis post discusses the differences between Drupal and WordPress, and also takes a quick look at a couple of other web frameworks. What are the benefits with each platform, and how do you know which one to choose?/p
/div
Thu, 05/16/2013 - 12:13
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even property=content:encodedpWe are pleased to announce that a href=http://drupal.org/project/commerce_kickstartCommerce Kickstart/a has won the Walkthrough documentation prize. The prize, which was determined by votes from Walkthrough.it backers, will use the Commerce Kickstart Drupal distribution to showcase the capabilities of Walkthrough.it./p
pCommerce Kickstart is the quickest way to get up and running with Drupal Commerce. The distribution provides everything to create a fully-featured demo store out of the box, complete with theme, catalog, and custom back office interface./p/div/div/div
Thu, 05/16/2013 - 08:00
div class=field field-name-field-ww-summary field-type-text-long field-label-hiddendiv class=field-itemsdiv class=field-item evenpa href=http://drupal.org/project/fieldblockField as Block/a is a lightweight module that allows you to display a field as a block. The same results can be achieved by using Panels, Display Suite or custom code but this module offers a lightweight alternative./p
pa href=http://drupal.org/project/cck_blocksCCK Blocks/a offers similar functionality, however on the project page they recommend that you use a href=http://drupal.org/project/fieldblockField as Block/a for new projects. It looks like CCK Blocks will be deprecated in favour of a href=http://drupal.org/project/fieldblockField as Block/a. For more details read a href=http://drupal.org/node/1920636issue #1920636/a (a href=http://drupal.org/node/1920636#comment-7084136comment #4/a)./p
/div/div/div
Thu, 05/16/2013 - 06:03
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item evenpToday Google a href=http://googlecloudplatform.blogspot.com/2013/05/ushering-in-next-generation-of.htmlannounced PHP support for Google App Engine/a! I have been one of the lucky folks who had early access and so of course I worked on getting a href=http://drupal.org/Drupal/a up and running on GAE. There are a few things that still need to be worked out which I will continue to discuss with the app engine team, but I have a a href=https://boombatower-drupal.appspot.com/working Drupal setup/a which I will detail below. Note that much of this may also apply to other PHP frameworks./p
h1Getting up and running/h1
pI will cover the steps specific to getting Drupal 7 em(notes for Drupal 6 along with branches in repository)/em up and running on App Engine and not how to use the SDK and development flow which is detailed in the documentation. For an example (minimal profile from core) of Drupal running on Google App Engine see a href=https://boombatower-drupal.appspot.com/boombatower-drupal.appspot.com/a./p
h2Sign up to be whitelisted for PHP runtime/h2
pCurrently, the PHP runtime requires you to a href=https://gaeforphp.appspot.com/sign up specifically for access/a. Assuming you have access you should be able to follow along with the steps below. Otherwise, the following steps will give you a feel for what it takes to get Drupal running on GAE./p
h2Create an app/h2
pCreate app by visiting a href=https://appengine.google.com/appengine.google.com/a and clicking emCreate Application/em, see the a href=https://developers.google.com/appengine/docs/adminconsole/indexdocumentation for more details/a./p
pimg src=/sites/blog.boombatower.com/files/appengine-create-app.png alt=Create an Application //p
h2Create a Cloud SQL Instance/h2
pFollow the a href=https://developers.google.com/cloud-sql/docs/before_you_begindocumentation for setting up a Cloud SQL Instance/a. Be sure to give your application access to the instance./p
pimg src=/sites/blog.boombatower.com/files/appengine-create-sql-instance.png alt=Create a Cloud SQL Instance //p
pOnce the instance has been created select the emSQL Prompt/em tab and create a database for your Drupal site as follows./p
div class=geshifilterpre class=mysql geshifilter-mysql style=font-family:monospace;CREATE DATABASE drupal;/pre/div
pimg src=/sites/blog.boombatower.com/files/appengine-create-sql-database.png alt=Create a Cloud SQL Database //p
h2Download Drupal/h2
pThere are a a href=https://github.com/boombatower/drupal-appengine/compare/7.x...7.x-appenginefew tweaks/a that need to be made to get Drupal to run properly on GAE which are explained below, but for the purposes of this walk-through one can simply download my branch containing all the changes from a href=https://github.com/boombatower/drupal-appenginegithub/a./p
div class=geshifilterpre class=bash geshifilter-bash style=font-family:monospace;git clone --branch 7.x-appengine https://github.com/boombatower/drupal-appengine.git
nbsp;
# or for Drupal 6
git clone --branch 6.x-appengine https://github.com/boombatower/drupal-appengine.git/pre/div
por a href=https://github.com/boombatower/drupal-appengine/archive/7.x-appengine.zipdownload as a zip/a or for Drupal 6 a href=https://github.com/boombatower/drupal-appengine/archive/6.x-appengine.zipdownload as a zip/a./p
h2Configure Drupal database settings/h2
pSince GAE does not allow the filesystem to be writeable one must configure the database settings ahead of time./p
pCopy emdefault.settings.php/em as emsettings.php/em and add the following bellow span class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpnbsp;$databasesnbsp;/spanspan style=color: #007700=nbsp;array();nbsp;/spanspan style=color: #0000BB?gt;/span/span/code/span around line em213/em./p
div class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpbr /$databasesnbsp;/spanspan style=color: #007700=nbsp;array();br //spanspan style=color: #0000BB$databases/spanspan style=color: #007700[/spanspan style=color: #DD0000'default'/spanspan style=color: #007700][/spanspan style=color: #DD0000'default'/spanspan style=color: #007700]nbsp;=nbsp;array(br /nbsp;nbsp;/spanspan style=color: #DD0000'driver'nbsp;/spanspan style=color: #007700=gt;nbsp;/spanspan style=color: #DD0000'mysql'/spanspan style=color: #007700,br /nbsp;nbsp;/spanspan style=color: #DD0000'database'nbsp;/spanspan style=color: #007700=gt;nbsp;/spanspan style=color: #DD0000'drupal'/spanspan style=color: #007700,nbsp;/spanspan style=color: #FF8000//nbsp;Thenbsp;databasenbsp;creatednbsp;abovenbsp;(examplenbsp;usednbsp;'drupal').br /nbsp;nbsp;/spanspan style=color: #DD0000'username'nbsp;/spanspan style=color: #007700=gt;nbsp;/spanspan style=color: #DD0000'root'/spanspan style=color: #007700,br /nbsp;nbsp;/spanspan style=color: #DD0000'password'nbsp;/spanspan style=color: #007700=gt;nbsp;/spanspan style=color: #DD0000''/spanspan style=color: #007700,br /nbsp;nbsp;/spanspan style=color: #FF8000//nbsp;Settingnbsp;thenbsp;'host'nbsp;keynbsp;willnbsp;usenbsp;anbsp;TCPnbsp;connectionnbsp;whichnbsp;isnbsp;notnbsp;supportednbsp;bynbsp;GAE.br /nbsp;nbsp;//nbsp;Thenbsp;namenbsp;ofnbsp;thenbsp;instancenbsp;creatednbsp;abovenbsp;(ex.nbsp;boombatower-drupal:drupal).br /nbsp;nbsp;/spanspan style=color: #DD0000'unix_socket'nbsp;/spanspan style=color: #007700=gt;nbsp;/spanspan style=color: #DD0000'/cloudsql/[INSTANCE]'/spanspan style=color: #007700,br //spanspan style=color: #FF8000//nbsp;nbsp;'unix_socket'nbsp;=gt;nbsp;'/cloudsql/boombatower-drupal:drupal',br /nbsp;nbsp;/spanspan style=color: #DD0000'prefix'nbsp;/spanspan style=color: #007700=gt;nbsp;/spanspan style=color: #DD0000''/spanspan style=color: #007700,br /);br //spanspan style=color: #0000BB?gt;/span/span/code/div
pFor Drupal 6 around line 91./p
div class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpbr /$db_urlnbsp;/spanspan style=color: #007700=nbsp;/spanspan style=color: #DD0000'mysql://root:@cloudsql__boombatower-drupal___drupal/drupal'/spanspan style=color: #007700;br //spanspan style=color: #0000BB?gt;/span/span/code/div
h2Push to App Engine/h2
pUpdate the emapplication/em name in the a href=https://github.com/boombatower/drupal-appengine/blob/7.x-appengine/app.yamlapp.yaml/a file to the one you created above and upload by following the a href=https://developers.google.com/appengine/docs/php/gettingstarted/uploadingdocumentation/a./p
div class=geshifilterpre class=yaml geshifilter-yaml style=font-family:monospace;# See https://developers.google.com/appengine/docs/php/config/appconfig.
nbsp;
application: drupal # lt;-- change this to your application
version: 1
runtime: php
api_version: 1
threadsafe: true
nbsp;
handlers:
# Default handler for requests (wrapper which will forward to index.php).
- url: /
script: wrapper.php
nbsp;
# Handle static requests.
- url: /(.*\.(ico$|jpg$|png$|gif$|htm$|html$|css$|js$))
# Location from which to serve static files.
static_files: \1
# Upload static files for static serving.
upload: (.*\.(ico$|jpg$|png$|gif$|htm$|html$|css$|js$))
# Ensures that a copy of the static files is left for Drupal during runtime.
application_readable: true
nbsp;
# Catch all unhandled requests and pass to wrapper.php which will simulate
# mod_rewrite by forwarding the requests to index.php?q=...
- url: /(.+)
script: wrapper.php/pre/div
div class=geshifilterpre class=bash geshifilter-bash style=font-family:monospace;appcfg.py update drupal//pre/div
h2Install/h2
pVisit a href=https://your-app.appspot.com/install.phpyour-app.appspot.com/install.php/a and follow the installation steps just as you would normally except that the database information will already be filled in. Go ahead and ignore the mbstring warning and note that the GAE team is looking into supporting a href=http://php.net/manual/book.mbstring.phpmbstring/a./p
h1Explanation of changes/h1
pIf you are interested in what changes/additions were made and the reasons for them continue reading, otherwise you should have a working Drupal install ready to explore! There are a few basic things that do not work perfectly out of the box on GAE. The changes can be seen by a href=https://github.com/boombatower/drupal-appengine/compare/7.x...7.x-appenginediffing the 7.x-appengine branch against the 7.x branch/a in my repository./p
h2File directory during installation/h2
pThe Drupal installer requires that the files directory be writeable, but GAE does not allow for local write access thus the requirement must be bypassed in order for the installation to complete./p
div class=geshifilterpre class=diff geshifilter-diff style=font-family:monospace;Author: boombatower lt;boombatower@google.comgt;
Date: Wed May 15 15:49:03 2013 -0700
nbsp;
Hack to trick Drupal into ignoring that file directory is not writable.
nbsp;
diff --git a/modules/system/system.install b/modules/system/system.install
index 1b037b8..9931aad 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -333,6 +333,8 @@ function system_requirements($phase) {
}
$is_writable = is_writable($directory);
$is_directory = is_dir($directory);
+ // Force Drupal to think the directories are writable during installation.
+ $is_writable = $is_directory = TRUE;
if (!$is_writable || !$is_directory) {
$description = '';
$requirements['file system']['value'] = $t('Not writable');/pre/div
h2Clean URLs/h2
pIn order to take advantage of clean urls, of which most sites take advantage, a href=http://httpd.apache.org/docs/current/mod/mod_rewrite.htmlmod_rewrite/a is required for a href=http://httpd.apache.org/Apache/a environments. Since GAE does not use Apache it does not support mod_rewrite and thus another solution is needed. The app.yaml can configure handlers which allow for wildcard matching which means multiple paths can easily be routed to a single script. Taking that one step further we can alter the span class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpnbsp;$_GET/spanspan style=color: #007700[/spanspan style=color: #DD0000'q'/spanspan style=color: #007700]/spanspan style=color: #0000BB?gt;/span/span/code/span variable just as mod_rewrite would so that Drupal functions properly. Rather than modify core this can be done via a a href=https://github.com/boombatower/drupal-appengine/blob/7.x-appengine/wrapper.phpwrapper/a script as show below (this should work well for other PHP applications)./p
div class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpbr //spanspan style=color: #FF8000/**br /nbsp;*nbsp;@filebr /nbsp;*nbsp;Providenbsp;mod_rewritenbsp;likenbsp;functionalitynbsp;andnbsp;correctnbsp;$_SERVER['SCRIPT_NAME'].br /nbsp;*br /nbsp;*nbsp;Passnbsp;throughnbsp;requestsnbsp;fornbsp;rootnbsp;phpnbsp;filesnbsp;andnbsp;forwardnbsp;allnbsp;othernbsp;requestsnbsp;tobr /nbsp;*nbsp;index.phpnbsp;withnbsp;$_GET['q']nbsp;equalnbsp;tonbsp;path.nbsp;Innbsp;termsnbsp;ofnbsp;hownbsp;thenbsp;requestsnbsp;willbr /nbsp;*nbsp;seemnbsp;pleasenbsp;seenbsp;thenbsp;followingnbsp;examples.br /nbsp;*br /nbsp;*nbsp;-nbsp;/install.php:nbsp;install.phpbr /nbsp;*nbsp;-nbsp;/update.php?op=info:nbsp;update.php?op=infobr /nbsp;*nbsp;-nbsp;/foo/bar:nbsp;index.php?q=/foo/barbr /nbsp;*nbsp;-nbsp;/:nbsp;index.php?q=/br /nbsp;*/br /br //spanspan style=color: #0000BB$pathnbsp;/spanspan style=color: #007700=nbsp;/spanspan style=color: #0000BBparse_url/spanspan style=color: #007700(/spanspan style=color: #0000BB$_SERVER/spanspan style=color: #007700[/spanspan style=color: #DD0000'REQUEST_URI'/spanspan style=color: #007700],nbsp;/spanspan style=color: #0000BBPHP_URL_PATH/spanspan style=color: #007700);br /br //spanspan style=color: #FF8000//nbsp;Providenbsp;mod_rewritenbsp;likenbsp;functionality.nbsp;Ifnbsp;anbsp;phpnbsp;filenbsp;innbsp;thenbsp;rootnbsp;directorybr ///nbsp;isnbsp;explicitelynbsp;requestednbsp;thennbsp;loadnbsp;thenbsp;file,nbsp;otherwisenbsp;loadnbsp;index.phpnbsp;andbr ///nbsp;setnbsp;getnbsp;variablenbsp;'q'nbsp;tonbsp;$_SERVER['REQUEST_URI'].br //spanspan style=color: #007700ifnbsp;(/spanspan style=color: #0000BBdirname/spanspan style=color: #007700(/spanspan style=color: #0000BB$path/spanspan style=color: #007700)nbsp;==nbsp;/spanspan style=color: #DD0000'/'nbsp;/spanspan style=color: #007700amp;amp;nbsp;/spanspan style=color: #0000BBpathinfo/spanspan style=color: #007700(/spanspan style=color: #0000BB$path/spanspan style=color: #007700,nbsp;/spanspan style=color: #0000BBPATHINFO_EXTENSION/spanspan style=color: #007700)nbsp;==nbsp;/spanspan style=color: #DD0000'php'/spanspan style=color: #007700)nbsp;{br /nbsp;nbsp;/spanspan style=color: #0000BB$filenbsp;/spanspan style=color: #007700=nbsp;/spanspan style=color: #0000BBpathinfo/spanspan style=color: #007700(/spanspan style=color: #0000BB$path/spanspan style=color: #007700,nbsp;/spanspan style=color: #0000BBPATHINFO_BASENAME/spanspan style=color: #007700);br /}br /elsenbsp;{br /nbsp;nbsp;/spanspan style=color: #0000BB$filenbsp;/spanspan style=color: #007700=nbsp;/spanspan style=color: #DD0000'index.php'/spanspan style=color: #007700;br /br /nbsp;nbsp;/spanspan style=color: #FF8000//nbsp;Providenbsp;mod_rewritenbsp;likenbsp;functionalitynbsp;bynbsp;usingnbsp;thenbsp;pathnbsp;whichnbsp;excludesbr /nbsp;nbsp;//nbsp;anynbsp;othernbsp;partnbsp;ofnbsp;thenbsp;requestnbsp;querynbsp;(ie.nbsp;ignoresnbsp;?foo=bar).br /nbsp;nbsp;/spanspan style=color: #0000BB$_GET/spanspan style=color: #007700[/spanspan style=color: #DD0000'q'/spanspan style=color: #007700]nbsp;=nbsp;/spanspan style=color: #0000BB$path/spanspan style=color: #007700;br /}br /br //spanspan style=color: #FF8000//nbsp;Overridenbsp;thenbsp;scriptnbsp;namenbsp;tonbsp;simulatenbsp;thenbsp;behaviornbsp;withoutnbsp;wrapper.php.br ///nbsp;Ensurenbsp;thatnbsp;$_SERVER['SCRIPT_NAME']nbsp;alwaysnbsp;beginsnbsp;withnbsp;anbsp;/nbsp;tonbsp;benbsp;consistentbr ///nbsp;withnbsp;HTTPnbsp;requestnbsp;andnbsp;thenbsp;valuenbsp;thatnbsp;isnbsp;normallynbsp;providednbsp;(notnbsp;whatnbsp;GAEbr ///nbsp;currentlynbsp;provides).br //spanspan style=color: #0000BB$_SERVER/spanspan style=color: #007700[/spanspan style=color: #DD0000'SCRIPT_NAME'/spanspan style=color: #007700]nbsp;=nbsp;/spanspan style=color: #DD0000'/'nbsp;/spanspan style=color: #007700.nbsp;/spanspan style=color: #0000BB$file/spanspan style=color: #007700;br /requirenbsp;/spanspan style=color: #0000BB$file/spanspan style=color: #007700;br //spanspan style=color: #0000BB?gt;/span/span/code/div
h2PHP $_SERVER['SCRIPT_NAME'] variable/h2
pThe span class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpnbsp;$_SERVER/spanspan style=color: #007700[/spanspan style=color: #DD0000'SCRIPT_NAME'/spanspan style=color: #007700]nbsp;/spanspan style=color: #0000BB?gt;/span/span/code/span implementation differs from Apache mod_php implementation which can cause issues with a variety of PHP applications. The variable matches the HTTP spec and not the filesystem when called through Apache./p
pFor example a script named emfoo.php/em contains the following./p
div class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpbr /var_dump/spanspan style=color: #007700(/spanspan style=color: #0000BB$_SERVER/spanspan style=color: #007700[/spanspan style=color: #DD0000'SCRIPT_NAME'/spanspan style=color: #007700]);br //spanspan style=color: #0000BB?gt;/span/span/code/div
pWhen executed from command line here are the results./p
div class=geshifilterpre class=bash geshifilter-bash style=font-family:monospace;$ php foo.php
string(7) quot;foo.phpquot;
nbsp;
$ php ./foo.php
string(9) quot;./foo.phpquot;/pre/div
pWhen invoked through Apache like emhttp://example.com/foo.php/em./p
div class=geshifilterpre class=bash geshifilter-bash style=font-family:monospace;string(8) quot;/foo.phpquot;/pre/div
pThe a href=http://php.net/manual/en/reserved.variables.server.phpdocumentation/a does not talk about this behavior (although many comments demonstrated the expected Apache behavior), but it is definitely depended on./p
pThe difference causes Drupal to format invalid URLs./p
div class=geshifilterpre class=text geshifilter-text style=font-family:monospace;example.com.foo.css (instead of ...com/foo.css)
example.comsubdir/foo.css (instead of ...com/subdir/foo.css)/pre/div
pDrupal derives the URL from span class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpnbsp;dirname/spanspan style=color: #007700()nbsp;/spanspan style=color: #0000BB?gt;/span/span/code/span of span class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpnbsp;$_SERVER/spanspan style=color: #007700[/spanspan style=color: #DD0000'SCRIPT_NAME'/spanspan style=color: #007700]nbsp;/spanspan style=color: #0000BB?gt;/span/span/code/span which will return . if no slashes or just / for something like /index.php./p
pThe wrapper script above solves this by ensuring that the emSCRIPT_NAME/em variable alway starts with a leading slash./p
h2HTTP requests/h2
pGAE does not yet support support outbound sockets for PHP (although supported for Python and Java) and if/when it does the preferred way will continue to be a href=https://developers.google.com/appengine/docs/php/urlfetch/overviewstreams/a due to automatic caching of outbound requests using urlfetch. I have included a small change to provide basic HTTP requests through drupal_http_request(). A proper solution would be to override the drupal_http_request_function variable and provide a fully functional alternative using streams. Drupal 8 has a href=http://drupal.org/node/1447736converted drupal_http_request()/a to use a href=http://guzzlephp.org/Guzzle/a which supports streams. Making a similar conversion for Drupal 7 seems like the cleanest way forward rather than reinventing the change./p
h2php.ini/h2
pGAE a href=https://developers.google.com/appengine/docs/php/runtime#Function-Supportdisables a number of functions for security reasons/a, but only emsoftly disables/em some functions which may then be enabled. Drupal provides access to emphpinfo()/em from emadmin/reports/status/em and uses output buffering, both of which are disabled by default. The included a href=https://github.com/boombatower/drupal-appengine/blob/7.x-appengine/php.iniphp.ini/a enables both functions in addition to emgetmypid/em which is used by emdrupal_random_bytes()/em./p
div class=geshifilterpre class=ini geshifilter-ini style=font-family:monospace;# See https://developers.google.com/appengine/docs/php/config/php_ini.
nbsp;
# Required for ob_*() calls which you can find by grepping.
# grep -nR '\sob_.*()' .
output_buffering = quot;1quot;
nbsp;
# See https://developers.google.com/appengine/docs/php/runtime#Functions-That-Must-Be-Manually-Enabled
# phpinfo: Provided on admin/reports/status under PHP -gt; quot;more informationquot;.
# getmypid: Used by drupal_random_bytes(), but not required.
google_app_engine.enable_functions = quot;getmypid, phpinfoquot;/pre/div
h1Future/h1
pI plan to continue working with the GAE team to ensure that support for Drupal can be provided in a clean and simple manner. Once current discussions have been resolved I hope to provide more formal documentation and support for Drupal./p
h2File handling/h2
pI worked on file support, but there were a number of upcoming changes that would make things much cleaner so I decided to wait. GAE provides a stream wrapper for a href=https://cloud.google.com/products/cloud-storageGoogle Cloud Storage/a which makes using the service very simple. Assuming you have a href=https://developers.google.com/appengine/docs/php/runtime#Function-Supportcompleted the prerequisites/a files on GCS may be accessed using standard PHP file handling functions as shown in the a href=https://developers.google.com/appengine/docs/php/googlestorage/overviewdocumentation/a./p
div class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpbr /$filenbsp;/spanspan style=color: #007700=nbsp;/spanspan style=color: #DD0000'gs://my_bucket/hello.txt'/spanspan style=color: #007700;br //spanspan style=color: #0000BBfile_put_contents/spanspan style=color: #007700(/spanspan style=color: #0000BB$file/spanspan style=color: #007700,nbsp;/spanspan style=color: #DD0000'hellonbsp;world'/spanspan style=color: #007700);br /br //spanspan style=color: #0000BB$contentsnbsp;/spanspan style=color: #007700=nbsp;/spanspan style=color: #0000BBfile_get_contents/spanspan style=color: #007700(/spanspan style=color: #0000BB$file/spanspan style=color: #007700);br //spanspan style=color: #0000BBvar_dump/spanspan style=color: #007700(/spanspan style=color: #0000BB$contents/spanspan style=color: #007700);nbsp;/spanspan style=color: #FF8000//nbsp;prints:nbsp;hellonbsp;worldbr //spanspan style=color: #0000BB?gt;/span/span/code/div
pUnfortunately, the wrapper does not currently support directories nor does emfile_exists()/em work properly. Keep in mind that the filesystem is flat so a file may be written to any path without explicitly creating the directory. Meaning one can write to emgs://bucket/foo/bar.txt/em without creating the directory emfoo/em. With that being the case it is possible to get some hacky support by simply disabling all the directory code in Drupal, but not really usable. It should be possible to hack support in through the stream wrapper since a href=https://developers.google.com/storage/docs/gsmanager#creatingfoldersdirectories are simply specially name files/a, but the app engine team has indicated they will look into the matter so hopefully this will be solved cleanly./p
pAssuming the stream wrappers are fixed up then support can be added in much the same way as that a href=http://drupal.org/project/amazons3Amazon S3 support is added/a except that no additional library will be needed./p
pAdditionally, the documentation also notes the following./p
blockquote
pDirect file uploads to your POST handler, without using the App Engine upload agent, are not supported and will fail./p
/blockquote
pIn order to support file uploads the form must be submitted to the url provided by emCloudStorageTools::createUploadUrl()/em and the forwarded result handled by Drupal. A benefit of proxying requests through uploader service is that uploaded files may be up to em100TB/em in size./p
h2Other/h2
pThere are a number of additional services provided as part of GAE of which Drupal could take advantage./p
ul
lia href=https://developers.google.com/appengine/docs/php/taskqueue/Task Queue API/a/li
lia href=https://developers.google.com/appengine/docs/php/users/Google account authentication/a/li
lia href=https://developers.google.com/appengine/docs/php/memcache/Memcache/a seems to work out of the box with the a href=http://drupal.org/project/memcachememcache module/a/li
lispan class=codeblock geshifiltercodespan style=color: #000000span style=color: #0000BBlt;?phpnbsp;$emSERVER/spanspan style=color: #007700[/spanspan style=color: #DD0000'HTTP_X_APPENGINE/em*'/spanspan style=color: #007700]nbsp;/spanspan style=color: #0000BB?gt;/span/span/code/span variables (like geo information)
Large number of services in a href=https://code.google.com/apis/console/API Console/a/li
/ul
h1Closing/h1
pHopefully this will be useful in getting folks up and running quickly on GAE with Drupal and understanding the caveats of the environment. Obviously there is a lot more to cover and I look forward to seeing what others publish on the matter./p
/div/div/divdiv class=field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfixh3 class=field-labelTags: /h3ul class=links inlineli class=taxonomy-term-reference-0a href=/taxonomy/term/2drupal/a/lili class=taxonomy-term-reference-1a href=/tags/drupal-6drupal 6/a/lili class=taxonomy-term-reference-2a href=/taxonomy/term/29drupal 7/a/lili class=taxonomy-term-reference-3a href=/tags/googlegoogle/a/lili class=taxonomy-term-reference-4a href=/tags/google-app-enginegoogle app engine/a/li/ul/div