Showing posts with label Neos. Show all posts
Showing posts with label Neos. Show all posts

Tuesday, July 21, 2015

An Image Web-Service for Documentarians

The Pain

I’ve been writing docs for the Neos project, watching for ways to make it easier for more people to get involved. The Neos Editor Guide (a user manual I’m writing) really needs a lot of screenshots to be effective for the end-users that need it. But, creating docs with visuals is annoying at best, even for a technical writer like me. Screenshots are annoying to produce, and keeping them up-to-date is painful. I want to create something to make this part of documentation easier to produce and maintain.

As you write the docs, you need to create screenshots. You could interrupt the flow of writing to go create the screenshot, and then struggle to get back into the flow of writing. Or, you could try and make notes on what screenshots are needed and deal with making them later. Hopefully, you won't miss any of the image placeholders in the docs. Whichever workflow you choose, switching contexts like that causes a lot of mental friction. Taking screenshots is annoying. Plus, it’s hard to get someone else to create the screenshots for you because they have to have both sets of tools as well.

And then, someone’s got to maintain the docs. How many times have you seen manuals where the screenshots are 5 or 10 years old? Once you write a doc with lots of screenshots, no one will ever update it; If someone does update it, they won’t update the screenshots. Screenshot maintenance is tedious, so no one does it.

The Seed of an Idea

What if we automated screenshots? There are a variety of tools that we could use to do this, including Behat, Cucumber, phantomjs, ffmpeg, etc. Then, you could describe the required screenshot in the doc you are writing and let Sphinx call the other tools to generate the screenshots. However, automating image creation will create a lot of images. If you keep your docs in a git repository, like I do, your git repository will quickly bloat with all those images; that kind of bloat makes git fetches slower and makes turns the git experience into an annoyance.

So, what if all of those screenshots were stored in some external service like Dropbox or Google Drive, or some other CDN(-like) service? Then, Sphinx (or whatever doc generator you use) would need a way to get the URI of those images without hard-coding them in the docs.

A Solution

So, I'm building a web-service for documentation visuals like screenshots. The service will take an image description (sent by Sphinx or some other doc generator like Jekyll, WikiMedia, or Confluence), and return an image URI. In the background it can let users upload the screenshots or automatically create them with something like Behat. Let's say goodbye to user manuals with screenshots that are out-of-date.

While writing the docs, the author just includes a description of the screenshot. Then, as far as the author is concerned, the description of the screenshot gets replaced with an actual screenshot. No more context switching between writing and taking screenshots. Someone else or some other program can deal with actually taking the screenshots.

Imagine a website like crowdin where people upload screenshots instead of localizations. The website would list the screenshot descriptions and let users upload a screenshot for each one. Automate what we can, and leave the rest to volunteers. That gives more people a way to contribute to the docs.

Thanks!

The TYPO3 Association funded the initial development of these ideas. Check out TYPO3 CMS at typo3.org. To all of the TYPO3 Association members who have supported this effort: Thank You!

Thursday, June 25, 2015

A generic screenshot webservice for documentation

@mathias.schreiber gave me some great feeback on Slack about the tools I want to build as part of my T3A budget (see my most recent blog post):
we plan to move this away from rst anyways, thus I ask myself how we benefit from the toolset
He also clarified that he's only talking about finding a tool that's easier to use, like Confluence, and it would only be for the manuals, not the reference documentation. And, he also tried to make it very clear that they aren't changing document formats right now, and there hasn't even been any official conversations in the ML. There are only plans, so far.

I'm really glad he pointed out this possibility on the horizon. Now, I need to generalize any tools I make so that they can be used by Confluence, Sphinx, or (almost) any other documentation tool that serves the needs of the project. Knowing it is on the horizon, I can design the tools to work in that context.

Here's my first stab at generalizing the screenshot tools.

Instead of starting with screenshot generation, I'm going to start with a simple web service that allows some kind of input (just an image id for the MVP, and later, it will accept a full behat scenario to describe the image that should be generated) and return a final image URI. (initially the image will serve up some placeholder/transparent image that is set to expire very quickly, and later the placeholder can be replaced with the generated image) This way, frequently regenerating screenshots in user manuals will not cause the git repo to bloat significantly. This will allow us to put the images directly in some kind of CDN service (an actual CDN if needed, or something like Dropbox or maybe Google Drive).

For the first MVP of this web service (which will only be accessible to a clients that are whitelisted, such as build.docs.typo3.org.), I will still manually generate any screenshots/screencasts. In the next phase, I will integrate behat (or something similar) that can describe the screenshots that should be generated. I'll add the ability to annotate screenshots later on.

This way, a description of the necessary screenshots can be embedded in manuals without requiring the document author to generate the screenshot (thus breaking the flow of writing the document). Then that description gets sent to the web service where something (or someone) takes the description and generates the required screenshot and makes it available at the URI provided by the web service. Even without automating the screenshot, this will allow the author, or other contributors, to go through the queue and generate all of the needed screenshots with the annotations.
This service would then need a sphinx plugin, or a wikimedia plugin, or a confluence plugin, or whatever tool is used to write manuals.

So, my budget can be useful to both TYPO3 and Neos, even if one or both teams decides to move the user manuals away from restructured text format.

Roar: Docs! Docs! Docs!

Update: I've responded to some great technical feedback on how my budget can help TYPO3 here.

This welcome conversation caught my attention on Twitter this week. I couldn’t get my comments to fit within 140 characters, so I’m responding here. Here are the tweets (without the twitter handles):
  • @sorenbryder: (tweet)
    “Documentation & Documentation Tools for Neos/Flow” for 2015 is EUR 13,750. At present, 0% of this budget have been used." Come on! #neoscms
  • @AskeErtmann: (tweet)This is a budget for @cognifloyd who wanted to spent time working on that now, but didn't start due to the budget situation..
  • @sorenbryder: (tweet)Okay, sounds good then. Better documentation is really needed, but this isn't news to anyone :)
  • @kdambekalns: (tweet)@sorenbryder And even better: The #TYPO3 documentation will probably profit from his work as well!
  • @mattLefaux: (tweet)go on
  • @kdambekalns: (tweet)Go [on] with… the work? Or explaining what it is about?
  • @mattLefaux: (tweet)if it’s a joint venture, the budget situation can easily be resolved. Need roar info
  • @kdambekalns: (tweet)So let's roar on :) The tooling (see the budget application…) could benefit all docs
I, @cognifloyd, am the budget owner for the “Documentation and Documentation Tools for Neos/Flow” 2015 budget. This is my roar! (check out the discussion of my budget application on forge. I'll just assume that you've read it in the rest of what I have to say)

As @kdambekalns said, I think the “#TYPO3 documentation will [...] profit from [my] work as well!”. Yes, my budget has “Neos” written all over it, but writing documentation alone is not enough. Dig a little deeper, and you’ll see how my work will benefit both projects. The key budget milestones are milestones 3 and 4:
  • “Infrastructure\Tools for [...] documentation contributions”, and
  • “Automated screenshot & video capture system for embedding in [rst docs]”.

I want to create a layer of glue between Sphinx (software that docs.typo3.org uses to render ReStructured Text, or rst) and screenshot/video capture tools like phantomjs and ffmpeg. Some people embed behat scenarios in rst, so that might be how I accomplish this. Others have already figured out how to make each of the other elements work. I want to bring the power of automated screenshots into the hands of the people that end up maintaining the docs.

When I applied for the budget, the Neos/Flow docs were ideal candidates for developing these tools. I was working on docs.typo3.org’s rendering infrastructure (more on this below), so I planned on writing those tools within that infrastructure. As a technical writer, I figured I’d be my own “domain expert” as I create the tools that I think will make it easier to create and maintain the docs. However, to be the “domain expert”, I can’t create the tools without actually writing some documentation. I need to write to identify exactly where writing/maintaining docs is painful. I need to write to make sure that the tools I create fit into the writing workflow as seemlessly as possible.

In fact, I’d started writing the Neos Editor Guide long before I applied for this budget. With this budget, I hope to make it easier for me and others to contribute to documentation efforts. It would take me a lot longer to identify gaps in TYPO3 docs than it takes to just continue what I’m already working on. Switching docs now would be like telling someone they have to rewrite all of their unit/functional tests before they can continue developing their software. Talk about lost productivity. The Neos docs are my “tests” (or at least my first test project), but TYPO3 will still get the benefit of the tools I create (or more appropriately, the tools I glue together).

I hope that TYPO3 Association members decide to continue funding my budget, even though the TYPO3 and Neos communities are separating into two overlapping communities. Both communities will benefit from better documentation tools and infrastructure. Plus, I will be able to more efficiently build these doc tools if I can continue building them as I write the docs I have already been working on.

“0% of this budget [has] been used.” (@sorenbryder)

Why haven’t I used that budget yet? Besides several personal time constraints, whenever I had time to work on something from a T3A budget this year, I prioritized building the docs infrastructure over writing/revising any of the docs. I started working on the docs infrastructure last year, and I wanted to finish that infrastructure project before I spent much time on my budget.

There has been a long-running project to replace the shell scripts that build the docs on docs.typo3.org with a web application that will make managing that rendering process easier. Any tools I write as part of my budget will be designed to plugin to this new rendering process. So, I thought working with the docs team first was the most logical course of action.

What was my budget for? Why did I apply for it?

Frankly, I applied because “docs”, for a lot of people, is a four-letter word. As @sorenbryder said, the need for better docs “isn’t news to anyone”.

But why? Why are docs always so out-of-date? Why don’t more people help keep them updated? Sure, English isn’t PHP (Sorry devs!), it’s not Esperanto, and, for most people, it’s not their native language. Writing good docs is hard work. It’s time consuming, and it requires a different mindset then writing good code does. Writing docs doesn’t feel profitable like selling another website gig, it’s not as enjoyable as a good YouTube playlist, and, when you finally get around to writing the docs, getting all the documentation tools together can be a nightmare.

There are a lot of gaps in the Neos and Flow docs. Given enough time, I could probably write new docs and revise the old docs, but that isn’t good enough for me. If I just “get it done”, the manuals I write would end up just as out-of-date as TYPO3’s Modern Template Building manual. No one has taken the time to substantially update that guide since it was written. Isn’t there a way to write a manual so that it’s easier for others to update it?

I’m a geek (ie I like PHP), English is my native language, and I’m a technical writer. Heck, I enjoy writing! I’m one of few people I know of in the TYPO3 community (and now the overlapping Neos community) with qualifications like that. Does that make me a “domain expert” when it comes to improving the documentation workflow? Maybe. I’m scratching an itch, and trying to do it in a way that will help as many people as possible.

So, I applied for a budget to help me find ways to make documentation easier for more people. But, how could I find the rough spots in writing/revising documentation without actually writing/revising a manual in the process?

That’s why I applied for my budget. There just had to be a better way!

What do screenshots have to do with that?

One of the most annoying, focus-stealing tasks in generating user documentation was generating the screenshots and short screencasts that I wanted to embed in the docs. Because they’re such a pain, and because no one takes the time to stop what they’re doing and regenerate them, I decided to automate that process. In searching the web, I discovered a variety of resources that make automating that a conceptually simple thing to do. I just need to glue the pieces together so that they can use descriptions embedded in rst docs to generate those screenshots/screencasts. If I could come up with a way to make that part of the documentaiton process better, then surely, I can find other process improvements too.

Another problem with screenshots is, everyone has their own way to take them. If numbers/labels are required, then they are going to look very inconsistent throughout a manual that gets updated by different people over the course of many years. If those screenshots are automatically generated instead, then our documentation will not only be more easy to update, but it’ll have more professional graphics as well.

What about the community split?

But, now, I’m faced with a dilemma. I didn’t know the TYPO3 and Neos communities were going to split. I think the split is good, as it is relieving a lot of tensions that have been building up in our community for many years. But, it sure makes it difficult for me to continue working on what I think will benefit both projects.

I have been in the TYPO3 community for over a decade, since version 3.4 or so of TYPO3. Back then, I was using TYPO3 to build a website for my high school. Since then, I’ve used TYPO3 and Neos in a variety of hobby and school projects. As a technical writer, I built a documentation website for one company first in TYPO3 CMS and then transitioned to using Neos, or TYPO3 Phoenix as it was called at the time. Sadly, none of the sites I’ve built still exist, but I don’t need those projects to consider myself a member of both the TYPO3 community and the Neos community.

Like I said at the beginning, I think my work will benefit both projects. My only problem was that I didn’t think a community split would happen this year. So, I made my budget mention Neos/Flow too many times instead of thinking/writing about how the TYPO3 project as a whole could benefit from these tools.

Conclusion/Request

If you are a TYPO3 Association member, please vote to honor the “Documentation & Documentation Tools for Neos/Flow” budget. I will make sure that screenshot automation and any other tools I create are smoothly integrated into the docs.typo3.org infrastructure. I’m already working hard on maintaining that infrastructure, and I look forwarding to making these features available to the docs that get rendered on docs.typo3.org.

Tuesday, August 6, 2013

Figuring out TDD

I want to use TDD in my GSoC project. Tests are important, and the benefits of testing are worth it.

Now, my only problem with TDD is, I'm not quite sure how to do it. Oh, I've got the mechanics in place (Travis is set up and ready to eat my github repo, and I think I've got phpunit setup locally. Heck I even have Jenkins on my local machine if I could ever get it configured right.), but whenever I go to write unit tests, I feel like I'm staring at a blank page in an old fashioned typewriter.

t  o  w  e  r
I feel like I'm staring at a blank page in an old fashioned typewriter. (Image from starside on flickr)
For a long time, I think my problem was an incomplete design. I knew I wanted to take stuff from a boilerplate, then "process it somehow", then put it in a derivative package. But I didn't know what that "somehow" looked like.

Well, I've figured out the main parts of that process now. I know what I want my API to look like (within PHP). So, I take my first example, and go line-by-line to make it work.

Loading Gist ....

So, let's take part of line 2:

new BlobQuery('Cognifire.SweetSitePackage');


How do I test this? Do unit tests test constructors? Is this a unit?

And so I'm back at that blank page again. I'm not quite sure what unit I'm testing. The constructor doesn't return anything, it just sets up the object. Should I add getters and setters for what should ultimately be protected properties just so that I can test that they are initialized correctly? That seems rather odd.

But TDD says don't write a line of code until you've written a failing test, so I feel stuck.

How do you approach TDD? Unit testing? What questions do you ask yourself to get past the stupid blank page?

Monday, June 10, 2013

Scattered design thoughts

So, I have notes scattered everywhere and I'm somewhat lost. I'm using this post to try and collect my notes, and get a better idea of where I am and where I'm going. Though you're welcome to browse through this, I don't expect these notes to make sense to anyone other than me.



BuilderFoundation provides a MetaModel for packages that other Builders will extend.

A Package can be built like FormDefinitions from TYPO3.Form
  • FormDefinitions have:
    • finishers <array>
    • processingRules <array>
    • elementsByIdentifier <array>
    • eleementsDefaultValue <array>
    • formFieldTypeManager <injected class>
    • validatorPresets <array>
    • finisherPresets <array>
    • setOptions (stuff that works with info from a YAML)
      • setRendererClassName
      • setRenderingOption
      • createFinisher
  • The FormFactory builds FormDefinitions
  • Use the name "presets" which would work as an options layer in general, or a "themes" layer in TemplateBuilder (a preset is a name + configuration; or iow it is a named set of configuration)
  • Based on YAML files
  • Using a yamlPersistenceManager
YAML files
  • Use superTypes inheritance concept (like in Forms and TYPO3CR: NodeTypes.yaml) to allow for things like mixins
  • Always get converted to arrays
  • considered using TypoScript, but YAML seems to fit how I'll use this better. (YAML is for data serialization. TypoScript helps in processing things)
  • YAML processors should always have at least one of dump() or load()
  • Each package has a configuration file in YAML
  • boilerplates and settings repositories should be added from the yaml (Cognifire\BuilderFoundation\boilerplateRepositories & derivativeRepositories)
  • Current configuration files
    • Settings.yaml
    • Routes.yaml
    • Objects.yaml
    • Policy.yaml
    • PackageStates.php
    • Caches.yaml
    • Views.yaml
  • It would be nice to be able to breakup boilerplate configurations so that there's one preset per file (or somethin like that). <whatever base name>.<preset name>.yaml
  • Will need a schema:
AbstractPackage: Boilerplates and Derivatives
  • not packageKey identified, but w/ UUID because packageKey might change several times during package build process
  • What gets stored in the package object is metadata about it's creation
    • a declarative set of steps--if you will--to allow the builder to recreate the same derivative but with another package key
    • Only part of this can be found out by parsing directory structures.
    • Instead, you
      • list Packages/<target repo>/*
      • read each <package>/Configuration/<yaml file>
  • Yaml file names (not satisfied with these names)
    • Themes.yaml (Builders might want to provide their own yaml file, like the templateBuilder where the word "themes" makes a lot of sense)
    • Possible names in Boilerplates:
      • Builder.Boilerplate.yaml
      • Boilerplate.yaml
        • Declared components (all available)
      • Boilerplate.presets.yaml
      • Boilerplate.presets.<something>.yaml
    • Possible names in Derivatives:
      • Builder.Derivative.yaml
      • Derivative.yaml
      • Boilerplate.Integrated.yaml
        • Declare which components were used and from where without introducing a dependency on the boilerplate
      • Builder.Template.yaml or Builder.Package.yaml
        • contains the presets or the final configuration, how all of declared components were put together
        • Builder specific?
    • Boilerplate.yaml and Derivative.yaml can be a collection of YAML files to keep the component definitions in the same folder as the component. Everything in that Boilerplate would apply only to that path. With one exception: Resources/Private/[Boilerplate || Derivative].yaml applies to the whole package. They should be restricted to the Resources folder, though, so that we don't have YAML files in the Classes/ or Tests/ folders. Boilerplate.yaml and Derivative.yaml should also not be in Settings/ as that is reserved for Presets.*.yaml for builder stuff as well as other configuration that is not builder-related.
    • Basically, this means that Boilerplates will store the snippets they use to build files in the Resources folder.
  • Boilerplate vs Derivative
    • Package Repository (Boilerplate vs Application)
    • Derivative
      • Root files (composer.json...)
      • Resources
      • Configuration
      • Documentation
      • Classes
      • Tests
      • Scripts
      • Migrations
      • Meta
  • Yaml files, rethought
    • <package>/Resources/Private/Boilerplate.yaml
      Declares which components/resources are available in boilerplate including:
      • Which builder is required to work with a particular set of files. Or maybe they would declare filetypes like x.html is fluid and y.html is handlebars so that the appropriate Builder can be used, and the Builder would say which filetypes it works with)
      • A versioning "namespace" of sorts, so that a boilerplate can include multiple versions of layouts/templates/partials (thinking of TwitterBootstrap v2 and v3). This would assist the migration service
      • Perhaps a list of presets that are available in the Boilerplate (though that should probably be based on what is in the Settings/)
    • <package>/Resources/Private/Derivative.yaml
      • Declares which components & presets have been used
        • from which boilerplate
        • and which boilerplate version (to assist with migrations)
      • Perhaps a list of which manual changes have been detected
      • This file would have the Eel selectors to say "insert [component] at [location] in [file]" including components from boilerplates and components that are added manually. This should be verbose enough that a Builder could regenerate the templates from the boilerplates (for the custom components [the 'changeset in Boilerplate math], maybe the builder could pull them out and store them in another Resources/Private/ folder so that it can keep track of manual changes.)
      • Though this should be human readable, only Builders will edit it. I can imagine people tweaking an Eel statement. But most of the file is for Builder metadata persistence.
    • <package>/Settings/
      Presets.[BuilderSpecific].[PresetName].yaml

      A preset configures a set of components to work together. This is the Builders' "options" layer. It does not define how the files are combined. That belongs in the Boilerplate.yaml (for what can be combined) or Deriative.yaml (for what has been combined) files.
      Should the BuilderSpecific part be singular or plural? You can have multiple presets in a Presets.Builder.yaml file, or break them out into individual Presets.Builder.Preset1.yaml and Presets.Builder.Preset2.yaml files.
      Someone could edit a Preset manually and use the Builder to make the change in their templates. These should be human-friendly. They would have to fire up the Builder to make the builder adjust whatever files are built with that preset (like changing a color in a LESS file).
      Examples of possible uses per builder (just examples, most are not part of GSoC project):
      • PackageBuilder
        • Presets.Package.CMS.yaml
        • Presets.Package.Flow.yaml
        • Presets.Package.Symfony.yaml (example extension of PackageBuilder)
      • TemplateBuilder
        • Presets.Theme.yaml
        • Presets.Theme.FixedLayout.yaml
        • Presets.Theme.AwesomeGreen.yaml
        • Presets.Theme.MyThemeName.yaml
        • Presets.Fluid.yaml (for stuff that doesn't quite fit the term "Theme"
      • TypoScriptBuilder
        • Presets.TypoScript.yaml
      • EmberBuilder or JavaScriptBuilder (Works with JavaScript stuff like Ember and Handlebars)
        • Presets.Ember.yaml
        • Presets.Ember.Handlebars.yaml
        • Presets.Handlebars.yaml
        • Presets.JS.yaml (maybe everything could be Presets.JS.*.yaml like Presets.JS.Ember.yaml and Presets.JS.Handlebars.yaml)
      • FormBuilder (if it switches to using BuilderFoundation at its core)
        • Presets.Form.yaml
        • Presets.Form.Cli.yaml
        • Presets.Form.Bootstrap.yaml
      • TranslationBuilder (works with .xlf files)
        • Presets.Translation.yaml (not sure how a TranslationBuilder would need Presets, but it's possible)
      • SchemaBuilder (a Resource that needs to be built. Different Builders might want to create a schema for what is allowed in their Presets.[Builder].*.yaml files, and they might not want to craft the schemas by hand)
      • OntologyBuilder/TaxonomyBuilder (Not sure this one will work with packages or boilerplates, but, the Builder concept still applies)
  • Yaml file contents Boilerplate vs Derivative (extendable yaml schema)
    • Boilerplate
      • relevant builder (like template builder)
        • components that can be built
          • include[superType]
          • Variations of each component
          • Options that apply to each component
      • presets
        • components 1,2,5
          • variations such and so
          • options
      • TemplateBuilder: (example specific builder)
        • Declare what is avilable
          • Components:
            • Variations
            • Options
          • Variations
          • Options (Theme in TemplateBuilder)
            • color1:
            • color2:
            • width:
        • Presets are pre-configured defaults / collections of components and options
          • Presets / <presetname>
            • components: 1, 2, 3
            • variation: A, B
            • options
    • Derivative
      • Has one preset that lists which
        • boilerplate components are in use
        • how they are configured
        • what options are set
      • Boilerplate.Integrated.yaml
        • declares components used from each boierplate
          • copied from boilerplate w/ boilerplate version
Spl*Iterators [Directory, FileSystem, Glob]:
  • Relationships
    • GlobIterator extends FileSystemIterator extends DirectoryIterator
    • RecursiveDirectoryIterator extends FileSystemIterator as well
    • GlobIterator is one level w/ glob pattern search
    • DirectoryIterator is one level
    • FileSystemIterator is just like DirectoryIterator but with flags that give more control over what current and key return.
    • RecursiveDirectoryIterator does many levels
  • Interesting FileSystemIterator Flags
    • ::CURRENT_AS_PATHNAME
    • ::KEY_AS_PATHNAME
    • ::KEY_AS_FILENAME
    • ::FOLLOW_SYMLINKS
    • ::NEW_CURRENT_AND_KEY (KEY_AS_FILENAME & CURRENT_AS_FILEINFO)
    • ::SKIP_DOTS
    • ::UNIX_PATHS (I'll want this one)
    • Current could return Pathname, or Filename or Fileinfo (which is a SplFileInfo object)
    • Key is just a numeric array key
  • SplFileInfo interesting methods (also available on DirectoryIterator and FileSystemIterator)
    • getBasename (can omit a suffix from path & filename)
    • getFilename
    • getPath (w/o filename)
    • openFile (creates SplFileObject to iterate ovver a file w/ fwrite, fpassthru...)
    • getRealPath (resolve links)
    • getExtension
    • getType (file, link, dir)
  • Streams
    • file:// -- for file access
    • glob://*.png -- for listing dir contents that match the glob
    • data: -- to encode stuff straight in files and treat it as a file/stream (RFC 2397)
      • data:text/plan,$data
      • data:text/plain;base64,$data
      • data:image/jpeg;base64;$image
    • resource:// -- flow specific only for stuff in resources of a particular package
      • The purpose of this is not to hide that something is a file, but to hide where it is stored (so that Flow can do the linking magic with all the public stuff in the Web/_Resources folder
Persistence
  • Flow injects the persistenceManagerInterface
  • There's no way to say which one flow will use, instead it is specified in objects.yaml (doctrine by default)
  • Mutliple concurrent Persistence backends won't be available until Flow 2.2 (or Flow 3 depending on how backwards compatible it is
    • define on repository basis what kind of DB to persist it in
    • This is not implemented yet due to lack of funding
    • I would rather reuse the flow persistence stuff where it makes sense, but I have to decouple everything until this is implemented. I'll copy lots of stuff to make it work. The thing is, a DB doesn't make any sense in my packages, even though I'm persisting stuff, the code assumes that persistence is always to a DB.
    • workaround is to put persistence stuff in the repository and not use @Flow\Entity and the like
  • "Models do not know (a lot) about Persistence (internals)"
  • Repository responsible for:
    • Saving object
    • persisting changes to object throughout lifetime (update DB as needed)
    • provide QL
      • handle DB retrieval
      • ensures only one instance in memory
    • provides the aggregate root
  • Comparing Radmiraal.CouchDB (doctrine branch) with normal doctrine persistence
    • @ODM\Document instead of @ORM\Entity or @Flow\Entity
    • replaces persistence manager w/ document manager
    • queries
      • no query on arbitrary properties
      • drops queries in favor of lucenQueries
      • setQueryMatchValue
    • both use persistenceManager
      • ->getObjectByIdentifier in generic
      • ->getIdentifierByObject in radmiraal
    • persistenceManager vs documentManager method names
      • add; persist
      • update; merge
      • remove; remove
      • createQueryForType; [createLuceneQuery, createNativeQuery, createQuery]
  • Doctrine's PersistenceManager uses the Annotations Driver
    • Annotations
      • Entity
        • map the repository / set CustomRepositoryClass
        • markReadOnly
    • loadMetaDataForClass
      • evaluatePropertyAnnotations
        • maps to column names, OneToOne, OneToMany, ManyToOne, ManyToMany
      • evaluateOverridesAnnotations
      • evaluateLifeCycleAnnotations
        • public methods
          • PrePersist
          • PostPersist
          • PreUpdate
          • PostUpdate
          • PreRemove
          • PostRemove
          • PostLoad
          • PreFlush
      • isTransient (yes if not entity or value object)
    • I want to use Flow/Validate
    • PersistenceManager fires
      • Yaml Configuration
        • All combined/cached like views.yaml

How other things interact w/ files
  • Parts of flow that work with files
    • Reflection uses cache to interact w/ Files
    • Fluid uses cache in compiler, and strings get passed to parser (it doesn't work w/ files)
    • TypoScript also parses strings, not files
    • Kickstarter
      • uses $templatePathAndFilename = resource://TYPO3.Kickstart/Private/...
      • shoves into renderTemplate()
      • then generateFile()
        • File::createDirectoryRecursviely
      • uses reflection for php files
      • hard codes important paths
        • Classes
        • Tests
        • Resources
      • Validate PackageKey ; PackageManager->isPackageAvailable
  • TYPO3\Flow\Utility
    • Environment
      • $this->environment->getPathToTemporaryDirectory()
    • Files
      • ::getUnixStylePath($cacheDirectory)
      • ::concatenatePaths($cacheDirectory)
      • ::readDirectoryRecursively($cacheDirectory)
      • ::createDirectoryRecursively($cacheDirectory)
      • ::emptyDirectoryRecursively($cacheDirectory)
  • php funcs
    • file_exists($pathAndFillename)
    • unlink($pathAndFilename)
    • file_get_contents($pathAndFilename)
    • file_put_contents($tempCacheEntryPathAndFilename, $data)
    • rename($tempCacheEntryPathAndFilename, $newPathAndFilename)
    • filesize($cacheEntryPathAndFilename)
    • filemtime($file)
    • new \DirectoryIterator ($this->cacheDirectory)
      • ->valid()
      • ->next()
      • ->isDot()
    • glob($pattern) find pathname matching the pattern
    • $fileHandle=fopen($this->logFileUrl, 'ab')
    • dirname($logFileUrl)
    • is_dir($)
    • is_link($)
    • stream_get_meta_data($fileHandle)
    • fclose($)
    • chmod( , )
    • touch()
    • fputs()

Thursday, May 30, 2013

Boilerplates and Builders in TYPO3 Neos

I will edit this article to edit the In-Scope and Out-of-Scope sections as needed. I wanted to publish this sooner rather than later.

GSoC Deliverables

In-Scope for this GSoC

I plan to deliver the following packages:
  • TYPO3.BuilderAbstract
  • TYPO3.TemplateBuilder
  • TYPO3.ZurbBoilerplate
  • TYPO3.BootstrapBoilerplate
Important features / components:
  • RoundTripService (very basic)
    • TemplateBuilder ties into the Fluid parser
  • MigrationService (very basic)
  • Backend Package Manipulation
    • Copy boilerplate package contents into a Deriative package
  • Boilerplate Configuration in YAML
    • Options layer that allows for multiple "presets" (like in TYPO3.Form). In the context of the TemplateBuilder, those "presets" should be exposed in the UI as a "theme" layer of options.
    • File manipulation indicators (a way to say that you inserted a fluid widget at a particular point in a template. These will be stored in the YAML files as Eel/FlowQuery because XPath only works for XML, and we will work with more than XML)
  • Fluidify SourceTemplates in TemplateBuilder (the backend for something like TemplaVoila)
Note: These are the names I prefer right now, though they've gone through several iterations. If these are not clear, please let me know. TYPO3.BuilderAbstract used to be called TYPO3.Boilerplate. TYPO3.TemplateBuilder used to be called TYPO3.FluidBuilder. SourceTemplates used to be called RawTemplates, NakedTemplates, or NakedBoilerplates.

Out-of-Scope for this GSOC

I will not have time to work much, if at all, on these:
  • Anything that works with TypoScript
  • Much of the UI (may be partially working thanks to TYPO3.Ice - but that's not my focus)
    • Including the TemplaVoila-like UI to select the various parts of a SourceTemplate file

Package Dependencies

Diagram of Package Dependencies
Boilerplates depend on the Builder that understands the files in them. Builders depend on the BuilderAbstract.
Builders extend the basic package manipulation of BuilderAbstract to handle particular filetypes
(eg TemplateBuilder handles Fluid files, and eventually will deal with SASS/LESS/CSS, etc).
BuilderAbstract also provides generic services Builder services (eg RoundTripService, MigrationService).
The PackageBuilder will probably orchestrate the other Builders when building a package, as they are complementary.
Derivative Packages never depend on the Boilerplates they are based on. They get modified copies of boilerplate files.

Producing a Derivative Package

This shows how Derivative Packages are made with the TemplateBuilder. The user has several choices:
(1) Selects a SourceTemplate (HTML/CSS) that will be converted to Fluid Templates in a Derivative Package
(2) Copy Fluid Templates from a Boilerplate Package and customize in a Derivative Package
(3) Start with nothing, and generate a Fluid Templates in a Derivative Package,
but insert some Fluid Widgets from a Boilerplate Package

I produced these images in yED. I can provide the original .graphml files if requested.

Saturday, May 25, 2013

Designing TYPO3.Boilerplate

So, I've been thinking about boilerplates in TYPO3 Flow + Neos (it's my GSOC project). After filling up a couple of whiteboards, I started writing stuff in my notebook. I don't expect my notes to mean very much to anyone but me, but I love to see how other people work, so I'm posting all of my notes so that you can see how I work.

edit: I removed the iframe because it was demanding more attention than it deserved. Check the notes out here.

Friday, May 10, 2013

Flow Package Types + Boilerplate Thoughts

So, there are a bunch of different package types for TYPO3 Flow. If you look in the packages folder you'll see several major kinds:

  • Distribution/ : The super-package that includes (via composer.json) all the other packages
    • Packages/
      • Applications: Flow-based apps
      • Framework: Flow's packages
      • Libraries: 3rd party libs and non-Flow packages
      • Sites: Neos site packages
      • Boilerplates: Meta-templates (part of my GSOC Proposal) that contain boilerplate files (php code, fluid templates, yaml, ...)
Then, there are some common naming conventions for Flow applications.
  • FooKickstarter: for initial creation of packages of type "Foo".
  • FooBuilder: to not only create, but edit "Foo" packages.
So, if my GSOC project is only going to be a one-time copy kind of a package, then I need to call it FluidKickstarter. If I give it the ability to edit and not just start templates, like I plan, then it should be called FluidBuilder.

I'm thinking of creating a Boilerplate framework. That way, there'd be a TYPO3.FluidBoilerplate that deals with Fluid specific template manipulation, but the TYPO3.Boilerplate package would contain the more abstract parts of dealing with any Boilerplate package. So that would mean there'd be something like this:
  • FooBoilerplate:
    • extends TYPO3.Boilerplate to assist builders in building "Foo" packages.
    • Not to be confused with packages in the Boilerplates folder, which contain raw material for the Boilerplate system to use in creating various types of packages (by FluidBuilder, PackageBuilder, FormBuilder, etc)
That solution feels awkward. Perhaps, there's a TYPO3.Boilerplate package, like before, that provides the abstract ways of working with Boilerplate packages. Then, the Builder packages would include a server-side layer that interacts with TYPO3.Boilerplate to do the building of packages (Fluid, Package (Flow), Form, Ember). Plus, each Builder package would contain a Frontend app that does the same thing as the backend, but in the browser. Then they would communicate over some RESTful API with Ember Data.

To date, that has been the solution for the other builder projects, so I think that would be a good convention to follow, with one change, in that I'll be using Boilerplate package, and hopefully other Builders will follow suite.

One of the issues with current Builders is that they store all of the template like stuff in their Private Resources folder. That's not very extensible, and though it might work for a lot of the current Builders, it won't work for FluidBuilder because I want there to be a lot of ready-made boilerplates that people can use to create whatever site they want as fast as they want. They should be able to make their own, or use Twitter Bootstrap, or H5BP, or whatever other grid system they enjoy.

Why? Flow is already fun for developers, but it needs to attract designers. So, Neos should be fun for designers to use, and Boilerplate packages are a good way to get there.

Ice and PackageBuilder and Boilerplates, Oh my!

So, I was just browsing github, and stumbled on TYPO3.Ice (ICE=Interface Construction Environment). Looking around, there's also a project on forge, and a git.typo3.org repo. I wanted to make sure it wasn't a previous effort to build TYPO3.FluidBuilder (my GSOC proposal), so I asked Rens on IRC what Ice was all about.

TYPO3.PackageBuilder

Apparently, it's part of the effort to create a TYPO3.PackageBuilder (see the github project, the forge project, and the git.typo3.org repo). PackageBuilder is like the next generation of the ExtensionBuilder that we know and love from TYPO3 CMS. It'll have a domain building UI, so that you can graphically create your domain objects and link them all together. I'm very excited to see someone working on the PackageBuilder.

TYPO3.Ice in TYPO3.PackageBuilder

PackageBuilder needs a UI similar to TYPO3.FormBuilder, so some of that interface was abstracted out, so that they could be reused in multiple packages. That common UI lives in TYPO3.Ice.

TYPO3.FluidBuilder

The best part of that? I'll probably be able to use TYPO3.Ice when I create TYPO3.FluidBuilder for a GSOC project. Maybe it'll be possible for me to create the UI portion in FluidBuilder after all, since it's mostly built for me already.

Boilerplates in TYPO3.PackageBuilder

Plus, looking through PackageBuilder's code, it looks like PackageBuilder could use the Boilerplate concept as well. Right now, there's Resources/Private/CodeTemplates. They've got both TYPO3 CMS and Flow templates, which could be put in separate boilerplate packages, so that you don't have to update the whole PackageBuilder package every time one of the boilerplates gets updated. Plus, then other organizations could create their own Flow Package Boilerplates, and use PackageBuilder to create packages with them.

Resources/Private/Generator could become Boilerplate packages in SiteKickstarter and Kickstart. Resources/Private/NewFormTemplates in FormBuilder could also be a Boilerplate, though one yaml file might not warrant it, so it could be treated like a virtual boilerplate. Potentially, other people could create Form boilerplates, though.

I'm very glad that I found out about Ice and PackageBuilder. It looks like my GSOC project will be very useful indeed (who wants their work to die and rot unused in the backroom?!). I hope that the Boilerplate concept, and the FluidBuilder will help more people to start using Flow and get involved with Neos.

Friday, May 3, 2013

Neos (dev-master) Hints

I'm using Neos from dev-master. Here are some things I've run up against with my group.

Workspaces

You can see and work in anyone's workspace, not just your own. If you want to work in the same workspace with someone, just edit the url.

@ in a Neos URL tells you what workspace you're looking at or using. For example, this shows that I'm in cognifloyd's workspace (hey, that's me!).


If I wanted to see the workspace for user john316 I would replace "@user-cognifloyd" with "@user-john316". Eventually, there will be some kind of access control to say which users can interact with which workspaces, but for now, once you're logged in, everything's fair game.

One way to use this is to share a workspace with a group of colleagues. Before I found this, we would each publish our changes (move them live) every time we wanted to share our work. This way, we can all work in the same workspace, and publish it live when everyone has finished their part.

Wireframe Mode

Resizing images in wireframe mode is currently broken.

Sections don't show up reliably until you've got content in them.

When you aren't in wireframe mode, you can just drag-n-drop elements to re-organize them. However, this feature isn't in wireframe mode. Instead, click "Inspect" in the lower left hand corner. You can rearrange the elements in there.



When you add a page, be sure to edit the nodepath in the right hand properties bar or you'll get some ugly urls. Neos doesn't seem to be automatically creating the nodepath based on the page name yet.