awonderphp / notreallypsrresourcemanager
A Proposal for a web application JS/CSS resouce manager
Installs: 4
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/awonderphp/notreallypsrresourcemanager
Requires
- php: ~7.1.0 || ~7.2.0
Requires (Dev)
- squizlabs/php_codesniffer: 3.*
- vimeo/psalm: ^0
This package is not auto-updated.
Last update: 2025-10-15 10:50:00 UTC
README
This is a set of interfaces that PHP libraries can use to provide sane management of third party JavaScript and CSS resources uses by the web applications.
The current namespace \AWonderPHP\NotReallyPsrResourceManager sucks and will
change. It was never intended as permanent. I was hoping a standards body would
want to take this idea and create some standard interfaces with fancy lingo
that includes RFC 2119.
While not strictly required, it is highly recommended that classes that
implement these interfaces extend the abstract classes within the
\AwonderPHP\FileResource
namespace.
That allows the resulting objects to be served by any class that understands
how to serve a FileResource object.
It is also intended that the JavaScriptResource and CssResource objects be generated from JSON configuration files as described in this document.
FileResource MethodsJavaScriptResource Interface MethodsCssResource Interface MethodsResourceManager InterfaceJSON Configuration FileJavaScript JSONCSS JSONFile System and Config File NamingWrapper Script
FileResource Methods
These methods are specified in both the JavaScriptResource and CssResource
interfaces and are identical to the methods of the same name in the abstract
\AwonderPHP\FileResource\FileResource class:
-
public function getMimeType()
Returns the$mimeproperty. -
public function getChecksum()
Returns the$checksumproperty. -
public function getCrossOrigin()
Returns the$crossoriginproperty. -
public function getFilePath()
Returns the$filepathproperty. -
public function validateFile()
If the$checksumproperty is set and the$filepathproperty is set and the file exists, returnstrueif the file matches the checksum andfalseif it does not. -
public function getSrcAttribute($prefix = null)
Builds the contents of thesrcorhrefattribute needed to embed the resource in a web page. Note that this will returnnullif the$urlschemeproperty ishttpand the file does not have a$checksumproperty that uses an algorithm in the$validIntegrityAlgoproperty. The optional parameter$prefixis a file system path to put in front of the$urlpathproperty, useful for web applications using a wrapper to serve the file. -
public function getIntegrityAttribute()
Builds the contents of anintegrityattribute, if the$checksumproperty uses a suitable algorithm. -
public function getTimestamp()
If the$lastmodeproperty is not null, returns a UNIX time stamp (seconds from UNIX epoch).
JavaScriptResource Interface Methods
These methods are in the JavaScriptResource interface but are not defined in
the previously mentioned FileResource abstract class.
-
getTypeAttribute()
What goes into thetypeattribute of a<script>node. Usually the MIME type but not always. -
getAsyncAttribute()
Whether or not the Booleanasyncattribute should be present. -
getDeferAttribute();
Whether or not the Booleandeferattribute should be present. -
getNoModuleAttribute()
Whether or not the Booleannomoduleattribute should be present. -
generateScriptDomNode($dom, $nonce = null)
Creates a\DOMNode<script>node, with an optional nonce. -
generateScriptString(bool $xml = false, $nonce = null)
Creates a string, either HTML or XHTML, for the script node with an optional nonce. If the$xmlparameter istrue, a string that is XML compliant should be returned (every attribute is akey="value"pair, Boolean attributes are usually justkey="key"but it does not really matter. Script node is self-closing). When the$xmlparameters isfalse, the default, an HTML compliant string is generated (boolean attributes may just bekeyand are not required to have an="value"and a self-closing script tags are not recognized as closed, so a closing</script>is required).
Both the generateScriptDomNode() and generateScriptString() methods should
call the getSrcAttribute() method, so the constructor of an implementing
class should have a property for the $prefix that is null by default but
can be set by the constructor.
CssResource Interface Methods
-
getTypeAttribute()
What goes into thetypeattribute of a CSS<link>node. This should ALWAYS returntext/css -
getMediaAttribute()
Returns what goes into themediaattribute of a CSS<link>node. This is rarely used, but it is very powerful and should be used more often IMHO as it can reduce the bandwidth the client needs to have to successfully use a web application. -
getHreflangAttribute()
Returns what goes into ahreflangattribute. When not null, it MUST be a BCP47 string. -
getReferrerPolicyAttribute()
Returns what goes into areferrerpolicyattribute of a CSS<link>node. I suspect it will not be used much, but it is there. -
getRelAttribute()
The contents of therelattribute, should returnstylesheet.
ResourceManager Interface
This is the interface that defines how web applications will interact get the
JavaScriptResource and CssResource objects that they need.
It describes two public methods:
-
getJavaScript(string $vendor, string $product, string $name, $version, $variant = null); -
getCSS(string $vendor, string $product, string $name, $version, $variant = null);
The web application calls those methods which will either return null if the
implementing class can not create the object, or it returns eith a
JavaScriptResource or CssResource implementing object, depending upon which
of the methods were called.
The Parameters:
-
$vendorString:
Lower case vendor string for who packaged the JavaScript or CSS, similar to the first level namespace in PSR-4 PHP classes but lower case. In Composer terms, it would be the top level directory within the Composer createdvendordirectory of your web application. -
$productString:
Lower case product string for the package the JavaScript or CSS is part of, similar to the second level namespace in PSR-4 PHP classes but lower case. In Composer terms, it would be the directory within the previously mentioned directory. -
$nameString:
The name of the JavaScript or CSS sans version and other info, e.g.jqueryorjquery-uiornormalize. -
$versionString or Integer:
The version needed, e.g.3.3.1to specifically ask for jQuery 3.3.1 or3.3to specifically ask for latest in3.3branch or simply3to ask for the latest in 3 branch. -
$variantString or Null:
The variant of the JavaScript needed, e.g.minfor minified orslimorslim.min.
With that information, the ResourceManager implementing class would be able
to find the JSON file describing the object and load it into an object.
The constructor for an implementing class should define the Base directory
directory resources are installed into so the methods can find the needed
configuration files and also the $prefix to use with the getSrcAttribute()
method.
Example Usage:
$base = "/whatever/path";
$RM = new \namespace\whatever\ImplementingClass($base);
$jsObj = $RM->getJavaScript('flossjs', 'jquery', 'jquery', 3, "min");
Then from $jsObj the web application can create the <script> node needed.
JSON Configuration File
The ResourceManager will hunt for a JSON configuration file that matches the resource the web application requests and then create the object to return from the JSON file. That needs a standard JSON file format.
Common JSON Elements to JavaScript and CSS
nameString, required:
The name of the script or css, sans version and variant, e.g.jquery.homepageString, not strictly required:
The URL homepage of the projectversionString, required:
The version of the script being described.licenseArray, required:
An array containing one or more applicable license for the script. Each element of the array should contain license name and a URL for the license.
Those fields are not utilized by the classes but are metadata that is useful to a system administrator. Other fields common to both JS and CSS:
mimeString, required:
The MIME type that should be used when serving the file.checksumString, recommended:
Thealgo:checksumdescribed in theFileResourceabstract class.filepathString, optional:
If the file is present on the server, the file system path to the file.lastmodString, recommended:
A string that can be parsed bystrtotime()to create a UNIX time stamp indicating when the file was last modified. For many projects, this is specified in a comment header of the file itself, and in those cases, that string should be used.srcurlString, required:
What should go in thesrcorhrefattribute. Must be parseable by theparse_urlfunction and internationalized domains should be in punycode.minifiedBoolean, optional:
Use of this field may be used by some implementations but is not required. It defines whether the JS/CSS in the file is minified.
JavaScript JSON
A sample of what a JavaScript JSON might look like:
{
"name": "jquery",
"homepage": "https://jquery.com/",
"version": "3.3.1",
"license": [
{
"name": "MIT",
"url": "https://jquery.org/license/"
}
],
"mime": "application/javascript",
"checksum": "sha256:160a426ff2894252cd7cebbdd6d6b7da8fcd319c65b70468f10b6690c45d02ef",
"filepath": "flossjs/jquery/js/jquery-3.3.1.min.js",
"lastmod": "2018-01-20T17:24Z",
"minified": true,
"srcurl": "/js/jquery-3.3.1.min.js"
}
JavaScript Specific Fields:
asyncBoolean, optional:
Only needed if it is desired to have that attribute, then set totrue.deferBoolean, optional:
Only needed if it is desired to have that attribute, then set totrue.nomoduleBoolean, optional:
Only needed if it is desired to have that attribute, then set totrue.- ??
type?? Needs Exploration:
In most cases, thetypeattribute is set to the MIME type, but it may be necessary to set it tomodularfor ES6 modular feature, I still need to learn about that.
CSS JSON
A sample of what a CSS JSON might look like needs to be written.
CSS Specific Fields:
mediaArray, optional:
An array containing the media tyes the CSS file applies to when it does not apply to everyone (browsers assumeallwhen not specified)hreflangString, optional:
The BCP47 language string that applies to the CSS file.referrerpolicyString, optional:
When present, must be one ofno-referrer,no-referrer-when-downgrade,origin,origin-when-cross-origin,unsafe-url-- browsers assumeno-referrer-when-downgradewhich is almost always the best policy for CSS style sheets. It is my opinion thatunsafe-urlshould never be used as it can leak information. It only has meaning when the remote server does not use TLS but your web application uses TLS and that scenario should be blocked by browsers anyway.
File System and Config File Naming
All scripts should be installed with a hierarchy of
$base/VendorName/ProductName where VendorName and ProductName are lower
case, as is Composer convention for PHP libraries.
In the case of Composer install of JS/CSS libraries, the Composer vendor
directory would be the $base directory.
Within the ProductName directory, an etc directory MUST exist that has
the JSON configuration files, and it is RECOMMENDED that the actual
JavaScript files reside in a js directory and CSS files reside in a css
directory.
An example of what this would look like is at AliceWonderMiscreations/CommonJS
Default configuration files would be named using:
ScriptName-Version-Variant.json.dist
Where ScriptName is the name of the script (e.g. jquery), Version is the
version of the script (e.g. 3.3.1), and if present, Variant would be the
script variant (e.g. min or slim or slim.min).
The default configuration should have the srcurl point to a local URL, e.g.
"srcurl": "/js/jquery-3.3.1.min.js",
When a system administrator wants to customize what is in the configuration,
they simply copy the file so that it no longer ends in .dist and then they
can modify it (e.g. to set srcurl to a CDN).
The ResourceManager MUST give priority to the configuration file without
the .dist if it is found.
With the major.minor.point versioning scheme, a configuration file should
exist for both major.minor and major that are identical to the default
configuration file for the most recent major.minor.point that match.
Wrapper Script
Web Applications that implement this MUST be able to handle requests to the
default /js/ and /css/ locations.
This can be accomplished by a wrapper script. An abstract class that extends
the FileWrapper class
to work for this has been written, that abstract class is part of the
AWonderPHP\FileResource
namespace.
An interface exists in this namespace that can be used to define a class that
extends the class that serves FileResource objects described above.
EOF