Duplicating Category Chunks, TV's and Snippets

Is there a script or plugin that will allow me to select a category within Chunks/TV’s and duplicate the whole folder?

I am iterating a site from one year to the next and all the previous years chunks need to be duplicated in order to receive the next years content and other aesthetic changes.

The easiest solution would be to just duplicate the whole of the MODX install and put it on a new hosting/domain. This is not possible as contexts used for year on year sub-domains. I am hoping that each subdomain pulls its content (chunks, TV’s and resources) from its year of content.

Hope the above makes sense.

Thanks for all advice in advance.

not sure, if I’m understanding correctly.
Sounds not like the best approach, if you have to copy stuff every year.

If you have every year within its own context, all in the same MODX - installation, you can just use the same chunks on every context.

If you want to duplicate chunks and TVs, you would need to rename them, too.

If you are looking for duplicating chunks and TVs from one installation to another. This would be possible with teleport

Maybe you could run a snippet with code like this:

$old_category_name = "2021";
$new_category_name = "2022";
$name_postfix = "_2022";

$old_category = $modx->getObject('modCategory', array('category' => $old_category_name));
$new_category = $modx->getObject('modCategory', array('category' => $new_category_name));

if ($old_category && $new_category){
    //Copy the chunks
    $chunks = $old_category->getMany('Chunks');
    foreach ($chunks as $chunk) {
        $new_chunk = $modx->newObject('modChunk');
        $fields = $chunk->toArray();
        $fields['name'] = $fields['name'] . $name_postfix; //change the name
        $fields['category'] = $new_category->get('id'); //change the category
    //Copy the snippets
    $snippets = $old_category->getMany('Snippets');
    foreach ($snippets as $snippet) {
        $new_snippet = $modx->newObject('modSnippet');
        $fields = $snippet->toArray();
        $fields['name'] = $fields['name'] . $name_postfix; //change the name
        $fields['category'] = $new_category->get('id'); //change the category
    //Copy the TVs
    $tvs = $old_category->getMany('TemplateVars');
    foreach ($tvs as $tv) {
        $new_tv = $modx->newObject('modTemplateVar');
        $fields = $tv->toArray();
        $fields['name'] = $fields['name'] . $name_postfix; //change the name
        $fields['category'] = $new_category->get('id'); //change the category
        if ($new_tv->save()){
            //Duplicate all media source associations
            $sourceElements = $modx->getCollection('sources.modMediaSourceElement',array(
                'object' => $tv->get('id'),
                'object_class' => 'modTemplateVar',
            if (is_array($sourceElements) && !empty($sourceElements)) {
                foreach ($sourceElements as $sourceElement) {
                    $newSourceElement = $modx->newObject('sources.modMediaSourceElement');
                        'object' => $new_tv->get('id'),
                        'object_class' => 'modTemplateVar',
                        'context_key' => $sourceElement->get('context_key'),
                        'source' => $sourceElement->get('source'),
            //Duplicate Template associations
            $templateVarTemplates = $tv->getMany('TemplateVarTemplates');
            if (is_array($templateVarTemplates) && !empty($templateVarTemplates)) {
                foreach ($templateVarTemplates as $templateVarTemplate) {
                    $newTemplateVarTemplate = $modx->newObject('modTemplateVarTemplate');
//$modx->cacheManager->refresh(); //maybe refresh the cache
return 'done';

Some caveats:

  • If you have static chunks/snippets I’m not sure this code is working.
  • The code doesn’t deal with property sets.
  • For TVs it duplicates the media source associations, but there are other associations (for example to the template) that maybe need to be duplicated too.