Regarding 2a: Smarty supports custom "resource" providers – see http://www.smarty.net/docsv2/en/template.resources.tpl . By default, all template names are treated as "file" resources (e.g. "CRM/Foo.tpl => file:/CRM/Foo.tpl"). My memory was a bit foggy yesterday, but now that I've had a chance to look it up, let me rewrite 2.*:
2.a: Implement a Smarty resource provider of type "ext" which locates templates in the extension directories. For example, "ext:/org.example.foo/CRM/Foo/Bar.tpl" would be a valid name of a Smarty template file. However, this doesn't support our overloading behavior – "ext:/org.example.foo/CRM/Foo/Bar.tpl" would not represent an overloaded version of "CRM/Foo/Bar.tpl". This approach sucks because it's not a drop-in work-a-like – various calls to $smarty->fetch and
{include}
would need to be reworked.
2.b. Change the default resource type from "file" to "civicrm", and implement a "civicrm" resource-provider which searches both the core codebase and all extension codebases. This is a drop-in work-a-like.
2.c. Change the default resource type from "file" to "civicrm", and implement a "civicrm" resource-provider which examines a cached listing of template names and file paths. The cached listing is constructed by scanning the content of core and of extensions (like the class-loading used by Drupal or PSR-0/Composer). This is probably more performant, but downstream devs will need to flush the cache when they add or remove template files.
This issue affects CiviEngage, CiviDiscount, and any module extensions produced by civix – all of them use the same basic technique of implementing hook_civicrm_config to modify the Smarty include path.
I don't see a way to do this without either (a) burdening downstream devs with more boilerplate in their main code or (b) patching core.For patching core, there are a few possible solutions:
1. Provide separate hooks for system initialization and Smarty initialization. The step which modifies the Smarty include path would run with the Smarty initialization hook (and not hook_civicrm_config).
2. Modify the Smarty template-lookup process to provide integral support for extensions/modules, e.g.
2.a. This could be done with specialized path mappings (e.g. "org.civicrm.civiengage:/CRM/Foo.php"). For better or worse, that would prevent extensions from overloading core tpl files.
2.b. Emulate the pattern used for class-loading in Drupal or PSR-0/Composer – e.g. when installing modules (or clearing caches), build the list of .tpl resources and store their path-mappings in a cache file.