We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 9207 ☆ A M B ☆
    • 2,475 Posts
    I know this is a perennial topic, but how should my component's files be organized while I develop and version it with Git? I know there have been several discussions that dealt with this (e.g. http://rtfm.modx.com/display/revolution20/Creating+a+3rd+Party+Component+Build+Script), but I don't think I've seen the topic addressed thoroughly.

    1. Where is a good place to store my_component's local version-controlled directory, with its children _build, assets, and core sub directories? It has to be somewhere inside the web root, but beyond that, does the location matter?

    2. How should I best tell MODX where to find my elements (Snippets, Chunks, etc.)? I spotted this tactic inside of the FormIt snippet, so I can see that I can optionally define a formit.core_path System Setting and leverage that to direct the file that gets included:

    require_once $modx->getOption('formit.core_path',null,$modx->getOption('core_path',null,MODX_CORE_PATH).'components/formit/').'model/formit/formit.class.php';


    That actually seems to be the best course... static elements aren't of much help here since there's no way to make them dynamic. E.g. you can't do something like
    [[++my_path]]to/my/git/repo/
    -- the file path has to be a file path and nothing dynamic that requires parsing.

    So the option to use a "scaffolding setting" while developing seems to hold the most promise, and counter-intuitively, using regular old include statements is more flexible than using Static Resources... but this only works for Snippets. How can I point my Chunk to get its contents from my special location AND have that same Chunk work when deployed live? I don't think it can be done without the use of an "Include Snippet".

    The frustrating thing here is that I can't seem to get around the necessity of having customized versions of my Snippets and Chunks etc. that are only relevant to my dev site -- e.g. a Chunk that references my custom versioned location, but when my package actually gets installed via the package manager, it will need to reference the "normal" location inside of core/components/. I could overcome this in my build script by slurping out the contents of all my elements and piping them into my vehicle, but that still raises the same question: where should they ultimately be stored? I feel like I'm a dog chasing his tail or that I'm complaining to Liza about a hole in the bucket that can't be fixed because (ultimately) there's a hole in the bucket.

    So unless I'm mistaken, the only solution here is to have one set of Chunks/Snippets/Templates etc. on the site where I'm developing stuff and then an entirely different set of them on a site where the package has been installed. Right? Am I missing something? But what does that mean for DEVELOPERS who want to contribute to existing projects? They would need to install an entirely different set of elements just in order to contribute to a given Extra. Is the solution to have 2 build scripts? One that deploys the package meant for public consumption and another that deploys the elements that a fellow developer would use?

    Oddly, this whole setup makes me yearn for SVN because with SVN I could have partial checkouts... I could store all my elements in the locations where they need to be when deployed, I could commit them up to the repo from those locations, and then when it came time to build, I could update a 3rd working copy and put them all together without having to strain my brain for a work-around that's even more awkward.

    Can any kind soul offer me some guidance here? Much appreciated.
      • 3749
      • 24,544 Posts
      Everett, you might take a look at the new version of MyComponent (http://bobsguides.com/mycomponent-tutorial.html). If you just install it and run Bootstrap, it will create the Example project in assets/mycomponents/example/. That's a pretty standard structure and the one I always use for my extras. Shaun and Mark use a very similar structure.

      If you use MyComponent, even just to get your project off the ground, you won't have to worry about where to put things. Once you edit the config file, it will put everything in a standard place and will create skeleton files for you to use.

      You put the git repo in assets/mycomponent/name_of_your_component, which is the root directory of your project. If you look at http://github.com/splittingred you'll see that all the repos are organized the same way. I think Mark's are the same way, as are mine, with a minor exception for the recent ones.

      The only difference in mine is that in the ones I've done with MyComponent, there's a separate directory under _build/data/ for each category. The elements in each category are under their category. It's a minor difference and it has no effect on the "real" assets and core directories which get transferred in the package. I do it so that a project can have multiple categories. The result, and I can't stress this enough, is that every package has the exact same build.transport.php file (no really). It can be customized, but it's almost never necessary. MyComponent will also create your lexicon files for you complete with language strings (no, really).

      Shaun's trick with the System Setting for the component's core path works very well with this structure for including classes. Here's an example:

      $path = $modx->getOption('newspublisher.core_path', null, $modx->getOption('core_path') . 'components/newspublisher/') . 'model/newspublisher/newspublisher.class.php';



      When the package is installed, that System Setting doesn't exist so the class is loaded from core/components/newspublisher/model/newspublisher/. In my dev. environment, it's loaded from

      assets/mycomponents/newspublisher/core/components/newspublisher/model/newspublisher/

      To get back to your main question, I have not had good luck developing with static elements. They just don't play well with Git for me. I'm always committing stuff that I didn't want to commit and vice versa. I also occasionally lose work altogether.

      The MyComponent solution to your question is two utilities: ExportObjects and ImportObjects. The first one takes what you have in MODX and updates the code and build files in your development dir. The second one does the opposite, it updates what's in MODX from the content of your development files. They are very quick and can be run from inside your code editor or from within MODX.

      I use ImportObjects and ExportObjects for Chunks, Templates, and TVs, which don't actually change that often for me.

      For snippets and plugins, I use something like this:

      return include 'c:/xampp/htdocs/addons/assets/mycomponents/newspublisher/core/components/newspublisher/elements/snippets/newspublisher.snippet.php';
      


      That way, the code for the snippets and plugins only exists in one place during development. In the newest version of MyComponent (not out yet), those files are ignored during ExportObjects (as are static elements) because the disk file is always up to date.

      I hope that all makes sense.
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
        • 9207 ☆ A M B ☆
        • 2,475 Posts
        Thanks Bob -- I've downloaded and installed your "MyComponent" package and I'm reviewing the docs... I'm a bit wobbly here so it might take me a while to grasp how to use this all...