-
-
Notifications
You must be signed in to change notification settings - Fork 825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CRM-20600 - AngularJS - Allowing hooking and static-caching #10085
Conversation
77e7c82
to
513023e
Compare
@totten wanna rebase this? |
bdca50a
to
f487792
Compare
I've rebased, continued the work, and updated the description to reflect current status. |
I've been doing some evaluation, and For example, a minimal formulation might be to put each alteration in a callback: // Pseudocode
function example_civicrm_angularPartials(HtmlCollection $html) {
$html->alter('~/crmMailing/EditMailingCtrl/2step.html', function(phpQueryObject $doc) {
$doc->find('[ng-form="crmMailingSubform"]')->attr('cat-stevens', 'ts(\'wild world\')');
});
} |
6ded087
to
3932bdf
Compare
jenkins, test this please |
b9f7b57
to
5f894cf
Compare
Some updates:
|
3bc9f64
to
f09c8c8
Compare
This PR moves the metadata about Angular modules out of Civi\Angular\Manager and into standalone files (`ang/*.ang.php`). This uses the same structure as `civix`. Also, this makes it easier to navigate between the JS/HTML/CSS/PHP content. To test that these changes were safe, I ran the following command before and after this commit: $ cv ev 'var_dump(Civi::service("angular")->getModules());' The results were substantively identical.
In the typical use-case, AssetBuilder can avoid an extra CMS+Civi bootstrap along with any build steps.
…s instead of *.html files Rationale: If the raw HTML can be modified via hook, then the HTML files are not truly representative of the final output. (e.g. a hook might add a new string to some HTML.) Note: This patch means that we no longer benefit from the cache in `CRM_Core_Resources_Strings`. However, the typical user still pulls data from a cache because we're using `AssetBuilder` to manage `angular-modules.json`. Note: `getStrings()` now requires a call to `getPartials()`, which is expected to become more expensive (firing a hook). To avoid building the partials twice, we introduce a private cache.
The default behavior is to include a `bundleUrl` for a bundle of "all Angular modules". However, some Angular modules like `crmMailing` are only displayed if the current user has permission to access them. This means that the list of "all Angular modules" can be different (depending on who you are; albeit in practice there's a small# of permutations). This patch ensures that two users who access a different list of modules will see a different `bundleUrl`.
If third-parties are allowed to alter the HTML content, then they may introduce new dependencies. This means that they'll need to delcare those dependencies. Tangentially, this will also make it easier to construct more optimized base-pages (e.g. "make a base-page with module X plus all its dependencies").
If third-parties are allowed to alter the HTML content, then they may introduce new dependencies. This means that they'll need to delcare those dependencies. This commit actually moves the declarations for any in-house modules to PHP.
Several modules depended on `crmResource` but didn't declare it.
…g HTML snippets via phpQuery
…injections This commit extracts the `Civi\Angular\Page\Main::registerResources()` and creates a new utility-class, `AngularLoader`. The `AngularLoader` can be used in new Angular base-pages, e.g. ```php class Example extends CRM_Core_Page { public function run() { $loader = new \Civi\Angular\AngularLoader(); $loader->setPageName('civicrm/foo/bar'); $loader->setModules(array('crmApp', '...')); $loader->load(); return parent::run(); } } ``` The `AngularLoader` only loads the resources or assets (JS/CSS/HTML files). To start Angular, you'll need to call `ng-app` or `angular.bootstrap(...)`. One way to do this is to define a page-template: ```html <!-- Example.tpl --> <div ng-app="crmApp"> <div ng-view></div> </div> ``` Or you can reuse the existing template: ```php public function getTemplateFileName() { return 'Civi/Angular/Page/Main.tpl'; } ``` Note: This is framed as a utility-class which loads the Angular resource files. It's not a page-class/base-class. This approach allows us to call the utility from other situations -- e.g. inject AngularJS onto an pre-existing page via hook. Doing that may or may not be wise, but the class-hierarchy shouldn't be the issue.
The default value (`auto`) behaves the same as the current behavior: enable caching in production mode, disable caching in debug mode. But it also allows you to enable/disable caching independent of the prod/debug mode.
Rebased. Resolved conflicts. Added setting This has been tested implicitly for a week or so during |
Test failures are common false-negatives. |
See civicrm/civicrm-core#10085 @totten I've added docs for this hook.
See civicrm/civicrm-core#10085 @totten I've added docs for this hook.
In AngularJS, the most visible policy decisions are made by arranging/enhancing a series of HTML fragments (aka "partials"). Partials are traditionally developed by hand then packaged/distributed as a static asset. This PR introduces an extra step where server-side PHP logic can programmatically manipulate the HTML fragments before Angular initializes. It's intended to allow extensions to alter UIs (a step toward OHUPA-2).
Allowing runtime alteration of AngularJS has implications for performance. To alleviate this concern, the PR also changes the caching strategy: instead of building the full JS/JSON/HTML assets on every request, we build the assets and store them as static, web-readable assets (under
[civicrm.files]
). For typical users, this should remove 500-1000ms from pageload.Example
Summary of changes
<div/>
vs<div></div>
;<img foo-bar>
vs<img foo-bar="">
). PHP'sDOMDocument
(and thereforephpQuery
) don't always preserve these details exactly. To ensure consistent behavior, this PR adds a consistency test (PartialSyntaxTest
).Civi\Angular\ChangeSet
: This provides a way to represent changes to Angular HTML.hook_civicrm_alterAngular
: This exposesCivi\Angular\Manager
andCivi\Angular\ChangeSet
so that you can modify any HTML file usingphpQuery
./sites/default/files/civicrm/persist/contribute/dyn/angular-modules.12341234.json
): There are a large number of partials. Doing hooks and translations creates more overhead, so this PR uses a new subsystem calledAssetBuilder
. On my local, this saves ~800ms when a typical user opens the Angular base page.assetCache
: This allows you to opt-in or out of using cache files. By default (auto
), caching is enabled production sites and disabled for debug sites.~/crmMailing/BlockSummary.html
has been altered, runcv ang:html:show --diff crmMailing/BlockSummary.html
Possible followups
These are non-blocker concerns that could merit follow-up:
crmMailingMgr
. Currently, you need to write directives which either take advantage of existing data-flow -- like CiviMail's autosave -- or setup strictly independent dataflow -- like an independent AJAX call. There's no in-between.Related PRs
civicrm.files
on multisite #10511 - Fix bug with accessing[civicrm.files]
on D7 multisite