Week 3: Add Joomla dependency injection architecture
This commit is contained in:
parent
453de17848
commit
0010c95b38
|
@ -0,0 +1,28 @@
|
|||
# IDE & System Related Files
|
||||
.buildpath
|
||||
.project
|
||||
.settings
|
||||
.DS_Store
|
||||
.idea
|
||||
.vscode
|
||||
.docker
|
||||
/docker-compose.yml
|
||||
/nbproject
|
||||
|
||||
# Local System File
|
||||
/octoconfig.php
|
||||
/.htaccess
|
||||
/web.config
|
||||
/php.ini
|
||||
|
||||
# Vendor directory handling
|
||||
/libraries/vendor
|
||||
|
||||
# OSX
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
Desktop.ini
|
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
// Saves the start time and memory usage.
|
||||
$startTime = microtime(1);
|
||||
$startMem = memory_get_usage();
|
||||
|
||||
if (file_exists(dirname(__DIR__) . '/defines.php'))
|
||||
{
|
||||
include_once dirname(__DIR__) . '/defines.php';
|
||||
}
|
||||
|
||||
if (!defined('_JDEFINES'))
|
||||
{
|
||||
define('JPATH_BASE', dirname(__DIR__));
|
||||
require_once JPATH_BASE . '/includes/defines.php';
|
||||
}
|
||||
|
||||
// Check for presence of vendor dependencies not included in the git repository
|
||||
if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_ROOT . '/media/vendor'))
|
||||
{
|
||||
echo file_get_contents(JPATH_ROOT . '/templates/system/build_incomplete.html');
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once JPATH_BASE . '/includes/framework.php';
|
||||
|
||||
// Set profiler start time and memory usage and mark afterLoad in the profiler.
|
||||
JDEBUG ? \Joomla\CMS\Profiler\Profiler::getInstance('Application')->setStart($startTime, $startMem)->mark('afterLoad') : null;
|
||||
|
||||
// Boot the DI container
|
||||
$container = \Joomla\CMS\Factory::getContainer();
|
||||
|
||||
/*
|
||||
* Alias the session service keys to the web session service as that is the primary session backend for this application
|
||||
*
|
||||
* In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects
|
||||
* is supported. This includes aliases for aliased class names, and the keys for aliased class names should be considered
|
||||
* deprecated to be removed when the class name alias is removed as well.
|
||||
*/
|
||||
$container->alias('session.web', 'session.web.administrator')
|
||||
->alias('session', 'session.web.administrator')
|
||||
->alias('JSession', 'session.web.administrator')
|
||||
->alias(\Joomla\CMS\Session\Session::class, 'session.web.administrator')
|
||||
->alias(\Joomla\Session\Session::class, 'session.web.administrator')
|
||||
->alias(\Joomla\Session\SessionInterface::class, 'session.web.administrator');
|
||||
|
||||
// Instantiate the application.
|
||||
$app = $container->get(\Joomla\CMS\Application\AdministratorApplication::class);
|
||||
|
||||
// Set the application as global app
|
||||
\Joomla\CMS\Factory::$application = $app;
|
||||
|
||||
// Execute the application.
|
||||
$app->execute();
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
// Global definitions
|
||||
$parts = explode(DIRECTORY_SEPARATOR, JPATH_BASE);
|
||||
array_pop($parts);
|
||||
|
||||
// Defines
|
||||
define('JPATH_ROOT', implode(DIRECTORY_SEPARATOR, $parts));
|
||||
define('JPATH_SITE', JPATH_ROOT);
|
||||
define('JPATH_CONFIGURATION', JPATH_ROOT);
|
||||
define('JPATH_ADMINISTRATOR', JPATH_ROOT . DIRECTORY_SEPARATOR . 'administrator');
|
||||
define('JPATH_LIBRARIES', JPATH_ROOT . DIRECTORY_SEPARATOR . 'libraries');
|
||||
define('JPATH_PLUGINS', JPATH_ROOT . DIRECTORY_SEPARATOR . 'plugins');
|
||||
define('JPATH_INSTALLATION', JPATH_ROOT . DIRECTORY_SEPARATOR . 'installation');
|
||||
define('JPATH_THEMES', JPATH_BASE . DIRECTORY_SEPARATOR . 'templates');
|
||||
define('JPATH_CACHE', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'cache');
|
||||
define('JPATH_MANIFESTS', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'manifests');
|
||||
define('JPATH_API', JPATH_ROOT . DIRECTORY_SEPARATOR . 'api');
|
||||
define('JPATH_CLI', JPATH_ROOT . DIRECTORY_SEPARATOR . 'cli');
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Version;
|
||||
use Joomla\Utilities\IpHelper;
|
||||
|
||||
// System includes
|
||||
require_once JPATH_LIBRARIES . '/bootstrap.php';
|
||||
|
||||
// Installation check, and check on removal of the install directory.
|
||||
if (!file_exists(JPATH_CONFIGURATION . '/configuration.php')
|
||||
|| (filesize(JPATH_CONFIGURATION . '/configuration.php') < 10)
|
||||
|| (file_exists(JPATH_INSTALLATION . '/index.php') && (false === (new Version)->isInDevelopmentState())))
|
||||
{
|
||||
if (file_exists(JPATH_INSTALLATION . '/index.php'))
|
||||
{
|
||||
header('Location: ../installation/index.php');
|
||||
|
||||
exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
echo 'No configuration file found and no installation code available. Exiting...';
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-Load configuration. Don't remove the Output Buffering due to BOM issues, see JCode 26026
|
||||
ob_start();
|
||||
require_once JPATH_CONFIGURATION . '/configuration.php';
|
||||
ob_end_clean();
|
||||
|
||||
// System configuration.
|
||||
$config = new JConfig;
|
||||
|
||||
// Set the error_reporting, and adjust a global Error Handler
|
||||
switch ($config->error_reporting)
|
||||
{
|
||||
case 'default':
|
||||
case '-1':
|
||||
|
||||
break;
|
||||
|
||||
case 'none':
|
||||
case '0':
|
||||
error_reporting(0);
|
||||
|
||||
break;
|
||||
|
||||
case 'simple':
|
||||
error_reporting(E_ERROR | E_WARNING | E_PARSE);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
break;
|
||||
|
||||
case 'maximum':
|
||||
case 'development': // <= Stays for backward compatibility, @TODO: can be removed in 5.0
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
error_reporting($config->error_reporting);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
define('JDEBUG', $config->debug);
|
||||
|
||||
// Check deprecation logging
|
||||
if (empty($config->log_deprecated))
|
||||
{
|
||||
// Reset handler for E_USER_DEPRECATED
|
||||
set_error_handler(null, E_USER_DEPRECATED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure handler for E_USER_DEPRECATED is registered
|
||||
set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (JDEBUG || $config->error_reporting === 'maximum')
|
||||
{
|
||||
// Set new Exception handler with debug enabled
|
||||
$errorHandler->setExceptionHandler(
|
||||
[
|
||||
new \Symfony\Component\ErrorHandler\ErrorHandler(null, true),
|
||||
'renderException'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correctly set the allowing of IP Overrides if behind a trusted proxy/load balancer.
|
||||
*
|
||||
* We need to do this as high up the stack as we can, as the default in \Joomla\Utilities\IpHelper is to
|
||||
* $allowIpOverride = true which is the wrong default for a generic site NOT behind a trusted proxy/load balancer.
|
||||
*/
|
||||
if (property_exists($config, 'behind_loadbalancer') && $config->behind_loadbalancer == 1)
|
||||
{
|
||||
// If Joomla is configured to be behind a trusted proxy/load balancer, allow HTTP Headers to override the REMOTE_ADDR
|
||||
IpHelper::setAllowIpOverrides(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We disable the allowing of IP overriding using headers by default.
|
||||
IpHelper::setAllowIpOverrides(false);
|
||||
}
|
||||
|
||||
unset($config);
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><title></title>
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
// NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message
|
||||
|
||||
// Define the application's minimum supported PHP version as a constant so it can be referenced within the application.
|
||||
define('JOOMLA_MINIMUM_PHP', '7.2.5');
|
||||
|
||||
if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<'))
|
||||
{
|
||||
die(
|
||||
str_replace(
|
||||
'{{phpversion}}',
|
||||
JOOMLA_MINIMUM_PHP,
|
||||
file_get_contents(dirname(__FILE__) . '/../templates/system/incompatible.html')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constant that is checked in included files to prevent direct access.
|
||||
* define() is used rather than "const" to not error for PHP 5.2 and lower
|
||||
*/
|
||||
define('_JEXEC', 1);
|
||||
|
||||
// Run the application - All executable code should be triggered through this file
|
||||
require_once dirname(__FILE__) . '/includes/app.php';
|
||||
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
##
|
||||
# @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
# @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
##
|
||||
|
||||
###########################################
|
||||
# ======= Set basic Security header =======
|
||||
|
||||
# Just enable the rules on the live site and exclude the dev sites
|
||||
<If "req('Host') == 'cms.builder.vdm'">
|
||||
<IfModule mod_headers.c>
|
||||
# X-XSS-Protection
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
# X-Frame-Options
|
||||
Header always set X-Frame-Options DENY
|
||||
# X-Content-Type nosniff
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
# Referrer Policy
|
||||
Header always set Referrer-Policy "no-referrer-when-downgrade"
|
||||
# Strict-Transport-Security
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
# Cross-Origin-Opener-Policy
|
||||
Header always set Cross-Origin-Opener-Policy "same-origin"
|
||||
# Content-Security-Policy
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'sha256-IxJ2MRv31XGmZD5ovlgSBrPmMjftYTJ3OM9/kLh6nBo=' 'sha256-QIsD5w9F5MPp3vlmsPHmbv0GZjN9ja3BuhcwpaWZuUw=' https://*.google-analytics.com https://www.googletagmanager.com https://*.pingdom.net; style-src 'self' 'sha256-4Su6mBWzEIFnH4pAGMOuaeBrstwJN4Z3pq/s1Kn4/KQ=' https://*.joomla.org https://fonts.googleapis.com; connect-src 'self' https://*.pingdom.net https://*.doubleclick.net https://*.google-analytics.com; frame-src 'self' https://*.googletagmanager.com; font-src 'self' https://fonts.gstatic.com https://*.joomla.org; img-src 'self' https://*.google-analytics.com https://*.googletagmanager.com https://*.joomla.org https://*.pingdom.net https://*.doubleclick.net https://*.githubusercontent.com https://*.travis-ci.org https://travis-ci.org; frame-ancestors 'self'; report-uri https://joomla.report-uri.com/r/t/csp/enforce"
|
||||
</IfModule>
|
||||
</If>
|
||||
|
||||
###########################################
|
||||
|
||||
###########################################
|
||||
# ======= Enable the Rewrite Engine =======
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# ======= No directory listings =======
|
||||
|
||||
IndexIgnore *
|
||||
Options +FollowSymLinks
|
||||
Options -Indexes
|
||||
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# === Optimal default expiration time ===
|
||||
|
||||
<IfModule mod_expires.c>
|
||||
# Enable expiration control
|
||||
ExpiresActive On
|
||||
|
||||
# Default expiration: 1 hour after request
|
||||
ExpiresDefault "now plus 1 hour"
|
||||
|
||||
# CSS and JS expiration: 1 week after request
|
||||
ExpiresByType text/css "now plus 1 week"
|
||||
ExpiresByType application/javascript "now plus 1 week"
|
||||
ExpiresByType application/x-javascript "now plus 1 week"
|
||||
|
||||
# Image files expiration: 1 month after request
|
||||
ExpiresByType image/bmp "now plus 1 month"
|
||||
ExpiresByType image/gif "now plus 1 month"
|
||||
ExpiresByType image/jpeg "now plus 1 month"
|
||||
ExpiresByType image/jp2 "now plus 1 month"
|
||||
ExpiresByType image/pipeg "now plus 1 month"
|
||||
ExpiresByType image/png "now plus 1 month"
|
||||
ExpiresByType image/svg+xml "now plus 1 month"
|
||||
ExpiresByType image/tiff "now plus 1 month"
|
||||
ExpiresByType image/vnd.microsoft.icon "now plus 1 month"
|
||||
ExpiresByType image/x-icon "now plus 1 month"
|
||||
ExpiresByType image/ico "now plus 1 month"
|
||||
ExpiresByType image/icon "now plus 1 month"
|
||||
ExpiresByType text/ico "now plus 1 month"
|
||||
ExpiresByType application/ico "now plus 1 month"
|
||||
ExpiresByType image/vnd.wap.wbmp "now plus 1 month"
|
||||
ExpiresByType application/vnd.wap.wbxml "now plus 1 month"
|
||||
ExpiresByType application/smil "now plus 1 month"
|
||||
|
||||
# Audio files expiration: 1 month after request
|
||||
ExpiresByType audio/basic "now plus 1 month"
|
||||
ExpiresByType audio/mid "now plus 1 month"
|
||||
ExpiresByType audio/midi "now plus 1 month"
|
||||
ExpiresByType audio/mpeg "now plus 1 month"
|
||||
ExpiresByType audio/x-aiff "now plus 1 month"
|
||||
ExpiresByType audio/x-mpegurl "now plus 1 month"
|
||||
ExpiresByType audio/x-pn-realaudio "now plus 1 month"
|
||||
ExpiresByType audio/x-wav "now plus 1 month"
|
||||
|
||||
# Movie files expiration: 1 month after request
|
||||
ExpiresByType application/x-shockwave-flash "now plus 1 month"
|
||||
ExpiresByType x-world/x-vrml "now plus 1 month"
|
||||
ExpiresByType video/x-msvideo "now plus 1 month"
|
||||
ExpiresByType video/mpeg "now plus 1 month"
|
||||
ExpiresByType video/mp4 "now plus 1 month"
|
||||
ExpiresByType video/quicktime "now plus 1 month"
|
||||
ExpiresByType video/x-la-asf "now plus 1 month"
|
||||
ExpiresByType video/x-ms-asf "now plus 1 month"
|
||||
</IfModule>
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# == Automatic compression of resources ==
|
||||
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript
|
||||
</IfModule>
|
||||
<IfModule mod_gzip.c>
|
||||
mod_gzip_on Yes
|
||||
mod_gzip_dechunk Yes
|
||||
mod_gzip_keep_workfiles No
|
||||
mod_gzip_can_negotiate Yes
|
||||
mod_gzip_add_header_count Yes
|
||||
mod_gzip_send_vary Yes
|
||||
mod_gzip_min_http 1000
|
||||
mod_gzip_minimum_file_size 300
|
||||
mod_gzip_maximum_file_size 512000
|
||||
mod_gzip_maximum_inmem_size 60000
|
||||
mod_gzip_handle_methods GET
|
||||
mod_gzip_item_include file \.(html?|txt|css|js|php|pl|xml|rb|py)$
|
||||
mod_gzip_item_include mime ^text/plain$
|
||||
mod_gzip_item_include mime ^text/html$
|
||||
mod_gzip_item_include mime ^text/xml$
|
||||
mod_gzip_item_include mime ^text/css$
|
||||
mod_gzip_item_include mime ^application/xml$
|
||||
mod_gzip_item_include mime ^application/xhtml+xml$
|
||||
mod_gzip_item_include mime ^application/rss+xml$
|
||||
mod_gzip_item_include mime ^application/javascript$
|
||||
mod_gzip_item_include mime ^application/x-javascript$
|
||||
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
|
||||
mod_gzip_item_include handler ^cgi-script$
|
||||
mod_gzip_item_include handler ^server-status$
|
||||
mod_gzip_item_include handler ^server-info$
|
||||
mod_gzip_item_include handler ^application/x-httpd-php
|
||||
mod_gzip_item_exclude mime ^image/.*
|
||||
</IfModule>
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# ======== Remove multiple slashes ========
|
||||
|
||||
RewriteCond %{HTTP_HOST} !=""
|
||||
RewriteCond %{THE_REQUEST} ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$ [OR]
|
||||
RewriteCond %{THE_REQUEST} ^[A-Z]+\s(.*/)/+\sHTTP/[0-9.]+$
|
||||
RewriteRule .* http://%{HTTP_HOST}/%1 [R=301,L]
|
||||
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# ======== Remove trailing slashes ========
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)/$ /$1 [R=301,L]
|
||||
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# ======== Redirect HTTP to HTTPS =========
|
||||
|
||||
#RewriteCond %{HTTPS} off
|
||||
#RewriteCond %{HTTP_HOST} ^framework.joomla.org$ [NC]
|
||||
#RewriteRule ^(.*)$ https://framework.joomla.org/$1 [R=301,L,QSA]
|
||||
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# ======== Redirect removed pages =========
|
||||
|
||||
#RewriteCond %{REQUEST_URI} ^/about
|
||||
#RewriteRule ^(.*)$ /contributors [R=301,L,QSA]
|
||||
|
||||
###########################################
|
||||
|
||||
|
||||
###########################################
|
||||
# ======== SEF URL Routing ========
|
||||
|
||||
# If the request is not for a static asset
|
||||
RewriteCond %{REQUEST_URI} !^/media/
|
||||
|
||||
# Or for a file that exists in the web directory
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
|
||||
# Rewrite the request to run the application
|
||||
RewriteRule (.*) index.php
|
||||
|
||||
###########################################
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
// Saves the start time and memory usage.
|
||||
$startTime = microtime(1);
|
||||
$startMem = memory_get_usage();
|
||||
|
||||
if (file_exists(dirname(__DIR__) . '/defines.php'))
|
||||
{
|
||||
include_once dirname(__DIR__) . '/defines.php';
|
||||
}
|
||||
|
||||
if (!defined('_JDEFINES'))
|
||||
{
|
||||
define('JPATH_BASE', dirname(__DIR__));
|
||||
require_once JPATH_BASE . '/includes/defines.php';
|
||||
}
|
||||
|
||||
// Check for presence of vendor dependencies not included in the git repository
|
||||
if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_ROOT . '/media/vendor'))
|
||||
{
|
||||
echo file_get_contents(JPATH_ROOT . '/templates/system/build_incomplete.html');
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once JPATH_BASE . '/includes/framework.php';
|
||||
|
||||
// Set profiler start time and memory usage and mark afterLoad in the profiler.
|
||||
JDEBUG && \Joomla\CMS\Profiler\Profiler::getInstance('Application')->setStart($startTime, $startMem)->mark('afterLoad');
|
||||
|
||||
// Boot the DI container
|
||||
$container = \Joomla\CMS\Factory::getContainer();
|
||||
|
||||
/*
|
||||
* Alias the session service keys to the web session service as that is the primary session backend for this application
|
||||
*
|
||||
* In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects
|
||||
* is supported. This includes aliases for aliased class names, and the keys for aliased class names should be considered
|
||||
* deprecated to be removed when the class name alias is removed as well.
|
||||
*/
|
||||
$container->alias('session.web', 'session.web.site')
|
||||
->alias('session', 'session.web.site')
|
||||
->alias('JSession', 'session.web.site')
|
||||
->alias(\Joomla\CMS\Session\Session::class, 'session.web.site')
|
||||
->alias(\Joomla\Session\Session::class, 'session.web.site')
|
||||
->alias(\Joomla\Session\SessionInterface::class, 'session.web.site');
|
||||
|
||||
// Instantiate the application.
|
||||
$app = $container->get(\Joomla\CMS\Application\SiteApplication::class);
|
||||
|
||||
// Set the application as global app
|
||||
\Joomla\CMS\Factory::$application = $app;
|
||||
|
||||
// Execute the application.
|
||||
$app->execute();
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
// Global definitions
|
||||
$parts = explode(DIRECTORY_SEPARATOR, JPATH_BASE);
|
||||
|
||||
// Defines.
|
||||
define('JPATH_ROOT', implode(DIRECTORY_SEPARATOR, $parts));
|
||||
define('JPATH_SITE', JPATH_ROOT);
|
||||
define('JPATH_CONFIGURATION', JPATH_ROOT);
|
||||
define('JPATH_ADMINISTRATOR', JPATH_ROOT . DIRECTORY_SEPARATOR . 'administrator');
|
||||
define('JPATH_LIBRARIES', JPATH_ROOT . DIRECTORY_SEPARATOR . 'libraries');
|
||||
define('JPATH_PLUGINS', JPATH_ROOT . DIRECTORY_SEPARATOR . 'plugins');
|
||||
define('JPATH_INSTALLATION', JPATH_ROOT . DIRECTORY_SEPARATOR . 'installation');
|
||||
define('JPATH_THEMES', JPATH_BASE . DIRECTORY_SEPARATOR . 'templates');
|
||||
define('JPATH_CACHE', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'cache');
|
||||
define('JPATH_MANIFESTS', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'manifests');
|
||||
define('JPATH_API', JPATH_ROOT . DIRECTORY_SEPARATOR . 'api');
|
||||
define('JPATH_CLI', JPATH_ROOT . DIRECTORY_SEPARATOR . 'cli');
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Version;
|
||||
use Joomla\Utilities\IpHelper;
|
||||
|
||||
// System includes
|
||||
require_once JPATH_LIBRARIES . '/bootstrap.php';
|
||||
|
||||
// Installation check, and check on removal of the install directory.
|
||||
if (!file_exists(JPATH_CONFIGURATION . '/configuration.php')
|
||||
|| (filesize(JPATH_CONFIGURATION . '/configuration.php') < 10)
|
||||
|| (file_exists(JPATH_INSTALLATION . '/index.php') && (false === (new Version)->isInDevelopmentState())))
|
||||
{
|
||||
if (file_exists(JPATH_INSTALLATION . '/index.php'))
|
||||
{
|
||||
header('Location: ' . substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], 'index.php')) . 'installation/index.php');
|
||||
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
echo 'No configuration file found and no installation code available. Exiting...';
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-Load configuration. Don't remove the Output Buffering due to BOM issues, see JCode 26026
|
||||
ob_start();
|
||||
require_once JPATH_CONFIGURATION . '/configuration.php';
|
||||
ob_end_clean();
|
||||
|
||||
// System configuration.
|
||||
$config = new JConfig;
|
||||
|
||||
// Set the error_reporting, and adjust a global Error Handler
|
||||
switch ($config->error_reporting)
|
||||
{
|
||||
case 'default':
|
||||
case '-1':
|
||||
|
||||
break;
|
||||
|
||||
case 'none':
|
||||
case '0':
|
||||
error_reporting(0);
|
||||
|
||||
break;
|
||||
|
||||
case 'simple':
|
||||
error_reporting(E_ERROR | E_WARNING | E_PARSE);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
break;
|
||||
|
||||
case 'maximum':
|
||||
case 'development': // <= Stays for backward compatibility, @TODO: can be removed in 5.0
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
error_reporting($config->error_reporting);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!defined('JDEBUG'))
|
||||
{
|
||||
define('JDEBUG', $config->debug);
|
||||
}
|
||||
|
||||
// Check deprecation logging
|
||||
if (empty($config->log_deprecated))
|
||||
{
|
||||
// Reset handler for E_USER_DEPRECATED
|
||||
set_error_handler(null, E_USER_DEPRECATED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure handler for E_USER_DEPRECATED is registered
|
||||
set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (JDEBUG || $config->error_reporting === 'maximum')
|
||||
{
|
||||
// Set new Exception handler with debug enabled
|
||||
$errorHandler->setExceptionHandler(
|
||||
[
|
||||
new \Symfony\Component\ErrorHandler\ErrorHandler(null, true),
|
||||
'renderException'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correctly set the allowing of IP Overrides if behind a trusted proxy/load balancer.
|
||||
*
|
||||
* We need to do this as high up the stack as we can, as the default in \Joomla\Utilities\IpHelper is to
|
||||
* $allowIpOverride = true which is the wrong default for a generic site NOT behind a trusted proxy/load balancer.
|
||||
*/
|
||||
if (property_exists($config, 'behind_loadbalancer') && $config->behind_loadbalancer == 1)
|
||||
{
|
||||
// If Joomla is configured to be behind a trusted proxy/load balancer, allow HTTP Headers to override the REMOTE_ADDR
|
||||
IpHelper::setAllowIpOverrides(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We disable the allowing of IP overriding using headers by default.
|
||||
IpHelper::setAllowIpOverrides(false);
|
||||
}
|
||||
|
||||
unset($config);
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><title></title>
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
// NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message
|
||||
|
||||
// Define the application's minimum supported PHP version as a constant so it can be referenced within the application.
|
||||
define('JOOMLA_MINIMUM_PHP', '7.2.5');
|
||||
|
||||
if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<'))
|
||||
{
|
||||
die(
|
||||
str_replace(
|
||||
'{{phpversion}}',
|
||||
JOOMLA_MINIMUM_PHP,
|
||||
file_get_contents(dirname(__FILE__) . '/templates/system/incompatible.html')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constant that is checked in included files to prevent direct access.
|
||||
* define() is used rather than "const" to not error for PHP 5.2 and lower
|
||||
*/
|
||||
define('_JEXEC', 1);
|
||||
|
||||
// Run the application - All executable code should be triggered through this file
|
||||
require_once dirname(__FILE__) . '/includes/app.php';
|
|
@ -0,0 +1,9 @@
|
|||
# Apache 2.4+
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.0-2.2
|
||||
<IfModule !mod_authz_core.c>
|
||||
Deny from all
|
||||
</IfModule>
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* Bootstrap file for the Joomla! CMS [with legacy libraries].
|
||||
* Including this file into your application will make Joomla libraries available for use.
|
||||
*
|
||||
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
// Set the platform root path as a constant if necessary.
|
||||
defined('JPATH_PLATFORM') or define('JPATH_PLATFORM', __DIR__);
|
||||
|
||||
// Detect the native operating system type.
|
||||
$os = strtoupper(substr(PHP_OS, 0, 3));
|
||||
|
||||
defined('IS_WIN') or define('IS_WIN', ($os === 'WIN'));
|
||||
defined('IS_UNIX') or define('IS_UNIX', (($os !== 'MAC') && ($os !== 'WIN')));
|
||||
|
||||
// Import the library loader if necessary.
|
||||
if (!class_exists('JLoader'))
|
||||
{
|
||||
require_once JPATH_PLATFORM . '/loader.php';
|
||||
|
||||
// If JLoader still does not exist panic.
|
||||
if (!class_exists('JLoader'))
|
||||
{
|
||||
throw new RuntimeException('Joomla Platform not loaded.');
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the autoloaders.
|
||||
JLoader::setup();
|
||||
|
||||
// Create the Composer autoloader
|
||||
/** @var \Composer\Autoload\ClassLoader $loader */
|
||||
$loader = require JPATH_LIBRARIES . '/vendor/autoload.php';
|
||||
|
||||
// We need to pull our decorated class loader into memory before unregistering Composer's loader
|
||||
class_exists('\\Joomla\\CMS\\Autoload\\ClassLoader');
|
||||
|
||||
$loader->unregister();
|
||||
|
||||
// Decorate Composer autoloader
|
||||
spl_autoload_register([new \Joomla\CMS\Autoload\ClassLoader($loader), 'loadClass'], true, true);
|
||||
|
||||
// Register the class aliases for Framework classes that have replaced their Platform equivalents
|
||||
require_once JPATH_LIBRARIES . '/classmap.php';
|
||||
|
||||
/**
|
||||
* Register the global exception handler. And set error level to server default error level.
|
||||
* The error level may be changed later in boot up process, after application config will be loaded.
|
||||
* Do not remove the variable, to allow to use it further, after including this file.
|
||||
*/
|
||||
$errorHandler = \Symfony\Component\ErrorHandler\ErrorHandler::register();
|
||||
\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::setTemplate(__DIR__ . '/../templates/system/fatal.php');
|
||||
|
||||
// Register the error handler which processes E_USER_DEPRECATED errors
|
||||
if (error_reporting() & E_USER_DEPRECATED)
|
||||
{
|
||||
set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
// Suppress phar stream wrapper for non .phar files
|
||||
$behavior = new \TYPO3\PharStreamWrapper\Behavior;
|
||||
\TYPO3\PharStreamWrapper\Manager::initialize(
|
||||
$behavior->withAssertion(new \TYPO3\PharStreamWrapper\Interceptor\PharExtensionInterceptor)
|
||||
);
|
||||
|
||||
if (in_array('phar', stream_get_wrappers()))
|
||||
{
|
||||
stream_wrapper_unregister('phar');
|
||||
stream_wrapper_register('phar', 'TYPO3\\PharStreamWrapper\\PharStreamWrapper');
|
||||
}
|
||||
|
||||
// Define the Joomla version if not already defined.
|
||||
defined('JVERSION') or define('JVERSION', (new \Joomla\CMS\Version)->getShortVersion());
|
||||
|
||||
// Set up the message queue logger for web requests
|
||||
if (array_key_exists('REQUEST_METHOD', $_SERVER))
|
||||
{
|
||||
\Joomla\CMS\Log\Log::addLogger(['logger' => 'messagequeue'], \Joomla\CMS\Log\Log::ALL, ['jerror']);
|
||||
}
|
||||
|
||||
// Register the Crypto lib
|
||||
JLoader::register('Crypto', JPATH_PLATFORM . '/php-encryption/Crypto.php');
|
||||
|
||||
// Register the PasswordHash library.
|
||||
JLoader::register('PasswordHash', JPATH_PLATFORM . '/phpass/PasswordHash.php');
|
|
@ -0,0 +1,790 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Static class to handle loading of libraries.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
abstract class JLoader
|
||||
{
|
||||
/**
|
||||
* Container for already imported library paths.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected static $classes = array();
|
||||
|
||||
/**
|
||||
* Container for already imported library paths.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected static $imported = array();
|
||||
|
||||
/**
|
||||
* Container for registered library class prefixes and path lookups.
|
||||
*
|
||||
* @var array
|
||||
* @since 3.0.0
|
||||
*/
|
||||
protected static $prefixes = array();
|
||||
|
||||
/**
|
||||
* Holds proxy classes and the class names the proxy.
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2
|
||||
*/
|
||||
protected static $classAliases = array();
|
||||
|
||||
/**
|
||||
* Holds the inverse lookup for proxy classes and the class names the proxy.
|
||||
*
|
||||
* @var array
|
||||
* @since 3.4
|
||||
*/
|
||||
protected static $classAliasesInverse = array();
|
||||
|
||||
/**
|
||||
* Container for namespace => path map.
|
||||
*
|
||||
* @var array
|
||||
* @since 3.1.4
|
||||
*/
|
||||
protected static $namespaces = array();
|
||||
|
||||
/**
|
||||
* Holds a reference for all deprecated aliases (mainly for use by a logging platform).
|
||||
*
|
||||
* @var array
|
||||
* @since 3.6.3
|
||||
*/
|
||||
protected static $deprecatedAliases = array();
|
||||
|
||||
/**
|
||||
* The root folders where extensions can be found.
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected static $extensionRootFolders = array();
|
||||
|
||||
/**
|
||||
* Method to discover classes of a given type in a given path.
|
||||
*
|
||||
* @param string $classPrefix The class name prefix to use for discovery.
|
||||
* @param string $parentPath Full path to the parent folder for the classes to discover.
|
||||
* @param boolean $force True to overwrite the autoload path value for the class if it already exists.
|
||||
* @param boolean $recurse Recurse through all child directories as well as the parent path.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for
|
||||
* your files.
|
||||
*/
|
||||
public static function discover($classPrefix, $parentPath, $force = true, $recurse = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ($recurse)
|
||||
{
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($parentPath),
|
||||
RecursiveIteratorIterator::SELF_FIRST
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$iterator = new DirectoryIterator($parentPath);
|
||||
}
|
||||
|
||||
/** @type $file DirectoryIterator */
|
||||
foreach ($iterator as $file)
|
||||
{
|
||||
$fileName = $file->getFilename();
|
||||
|
||||
// Only load for php files.
|
||||
if ($file->isFile() && $file->getExtension() === 'php')
|
||||
{
|
||||
// Get the class name and full path for each file.
|
||||
$class = strtolower($classPrefix . preg_replace('#\.php$#', '', $fileName));
|
||||
|
||||
// Register the class with the autoloader if not already registered or the force flag is set.
|
||||
if ($force || empty(self::$classes[$class]))
|
||||
{
|
||||
self::register($class, $file->getPath() . '/' . $fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnexpectedValueException $e)
|
||||
{
|
||||
// Exception will be thrown if the path is not a directory. Ignore it.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the list of registered classes and their respective file paths for the autoloader.
|
||||
*
|
||||
* @return array The array of class => path values for the autoloader.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static function getClassList()
|
||||
{
|
||||
return self::$classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the list of deprecated class aliases.
|
||||
*
|
||||
* @return array An associative array with deprecated class alias data.
|
||||
*
|
||||
* @since 3.6.3
|
||||
*/
|
||||
public static function getDeprecatedAliases()
|
||||
{
|
||||
return self::$deprecatedAliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the list of registered namespaces.
|
||||
*
|
||||
* @return array The array of namespace => path values for the autoloader.
|
||||
*
|
||||
* @since 3.1.4
|
||||
*/
|
||||
public static function getNamespaces()
|
||||
{
|
||||
return self::$namespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a class from specified directories.
|
||||
*
|
||||
* @param string $key The class name to look for (dot notation).
|
||||
* @param string $base Search this directory for the class.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for
|
||||
* your files.
|
||||
*/
|
||||
public static function import($key, $base = null)
|
||||
{
|
||||
// Only import the library if not already attempted.
|
||||
if (!isset(self::$imported[$key]))
|
||||
{
|
||||
// Setup some variables.
|
||||
$success = false;
|
||||
$parts = explode('.', $key);
|
||||
$class = array_pop($parts);
|
||||
$base = (!empty($base)) ? $base : __DIR__;
|
||||
$path = str_replace('.', DIRECTORY_SEPARATOR, $key);
|
||||
|
||||
// Handle special case for helper classes.
|
||||
if ($class === 'helper')
|
||||
{
|
||||
$class = ucfirst(array_pop($parts)) . ucfirst($class);
|
||||
}
|
||||
// Standard class.
|
||||
else
|
||||
{
|
||||
$class = ucfirst($class);
|
||||
}
|
||||
|
||||
// If we are importing a library from the Joomla namespace set the class to autoload.
|
||||
if (strpos($path, 'joomla') === 0)
|
||||
{
|
||||
// Since we are in the Joomla namespace prepend the classname with J.
|
||||
$class = 'J' . $class;
|
||||
|
||||
// Only register the class for autoloading if the file exists.
|
||||
if (is_file($base . '/' . $path . '.php'))
|
||||
{
|
||||
self::$classes[strtolower($class)] = $base . '/' . $path . '.php';
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we are not importing a library from the Joomla namespace directly include the
|
||||
* file since we cannot assert the file/folder naming conventions.
|
||||
*/
|
||||
else
|
||||
{
|
||||
// If the file exists attempt to include it.
|
||||
if (is_file($base . '/' . $path . '.php'))
|
||||
{
|
||||
$success = (bool) include_once $base . '/' . $path . '.php';
|
||||
}
|
||||
}
|
||||
|
||||
// Add the import key to the memory cache container.
|
||||
self::$imported[$key] = $success;
|
||||
}
|
||||
|
||||
return self::$imported[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the file for a class.
|
||||
*
|
||||
* @param string $class The class to be loaded.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static function load($class)
|
||||
{
|
||||
// Sanitize class name.
|
||||
$key = strtolower($class);
|
||||
|
||||
// If the class already exists do nothing.
|
||||
if (class_exists($class, false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the class is registered include the file.
|
||||
if (isset(self::$classes[$key]))
|
||||
{
|
||||
$found = (bool) include_once self::$classes[$key];
|
||||
|
||||
if ($found)
|
||||
{
|
||||
self::loadAliasFor($class);
|
||||
}
|
||||
|
||||
// If the class doesn't exists, we probably have a class alias available
|
||||
if (!class_exists($class, false))
|
||||
{
|
||||
// Search the alias class, first none namespaced and then namespaced
|
||||
$original = array_search($class, self::$classAliases) ? : array_search('\\' . $class, self::$classAliases);
|
||||
|
||||
// When we have an original and the class exists an alias should be created
|
||||
if ($original && class_exists($original, false))
|
||||
{
|
||||
class_alias($original, $class);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly register a class to the autoload list.
|
||||
*
|
||||
* @param string $class The class name to register.
|
||||
* @param string $path Full path to the file that holds the class to register.
|
||||
* @param boolean $force True to overwrite the autoload path value for the class if it already exists.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for
|
||||
* your files.
|
||||
*/
|
||||
public static function register($class, $path, $force = true)
|
||||
{
|
||||
// When an alias exists, register it as well
|
||||
if (array_key_exists(strtolower($class), self::$classAliases))
|
||||
{
|
||||
self::register(self::stripFirstBackslash(self::$classAliases[strtolower($class)]), $path, $force);
|
||||
}
|
||||
|
||||
// Sanitize class name.
|
||||
$class = strtolower($class);
|
||||
|
||||
// Only attempt to register the class if the name and file exist.
|
||||
if (!empty($class) && is_file($path))
|
||||
{
|
||||
// Register the class with the autoloader if not already registered or the force flag is set.
|
||||
if ($force || empty(self::$classes[$class]))
|
||||
{
|
||||
self::$classes[$class] = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a class prefix with lookup path. This will allow developers to register library
|
||||
* packages with different class prefixes to the system autoloader. More than one lookup path
|
||||
* may be registered for the same class prefix, but if this method is called with the reset flag
|
||||
* set to true then any registered lookups for the given prefix will be overwritten with the current
|
||||
* lookup path. When loaded, prefix paths are searched in a "last in, first out" order.
|
||||
*
|
||||
* @param string $prefix The class prefix to register.
|
||||
* @param string $path Absolute file path to the library root where classes with the given prefix can be found.
|
||||
* @param boolean $reset True to reset the prefix with only the given lookup path.
|
||||
* @param boolean $prepend If true, push the path to the beginning of the prefix lookup paths array.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function registerPrefix($prefix, $path, $reset = false, $prepend = false)
|
||||
{
|
||||
// Verify the library path exists.
|
||||
if (!is_dir($path))
|
||||
{
|
||||
$path = (str_replace(JPATH_ROOT, '', $path) == $path) ? basename($path) : str_replace(JPATH_ROOT, '', $path);
|
||||
|
||||
throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
|
||||
}
|
||||
|
||||
// If the prefix is not yet registered or we have an explicit reset flag then set set the path.
|
||||
if ($reset || !isset(self::$prefixes[$prefix]))
|
||||
{
|
||||
self::$prefixes[$prefix] = array($path);
|
||||
}
|
||||
// Otherwise we want to simply add the path to the prefix.
|
||||
else
|
||||
{
|
||||
if ($prepend)
|
||||
{
|
||||
array_unshift(self::$prefixes[$prefix], $path);
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$prefixes[$prefix][] = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Offers the ability for "just in time" usage of `class_alias()`.
|
||||
* You cannot overwrite an existing alias.
|
||||
*
|
||||
* @param string $alias The alias name to register.
|
||||
* @param string $original The original class to alias.
|
||||
* @param string|boolean $version The version in which the alias will no longer be present.
|
||||
*
|
||||
* @return boolean True if registration was successful. False if the alias already exists.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function registerAlias($alias, $original, $version = false)
|
||||
{
|
||||
// PHP is case insensitive so support all kind of alias combination
|
||||
$lowercasedAlias = strtolower($alias);
|
||||
|
||||
if (!isset(self::$classAliases[$lowercasedAlias]))
|
||||
{
|
||||
self::$classAliases[$lowercasedAlias] = $original;
|
||||
|
||||
$original = self::stripFirstBackslash($original);
|
||||
|
||||
if (!isset(self::$classAliasesInverse[$original]))
|
||||
{
|
||||
self::$classAliasesInverse[$original] = array($lowercasedAlias);
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$classAliasesInverse[$original][] = $lowercasedAlias;
|
||||
}
|
||||
|
||||
// If given a version, log this alias as deprecated
|
||||
if ($version)
|
||||
{
|
||||
self::$deprecatedAliases[] = array('old' => $alias, 'new' => $original, 'version' => $version);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a namespace to the autoloader. When loaded, namespace paths are searched in a "last in, first out" order.
|
||||
*
|
||||
* @param string $namespace A case sensitive Namespace to register.
|
||||
* @param string $path A case sensitive absolute file path to the library root where classes of the given namespace can be found.
|
||||
* @param boolean $reset True to reset the namespace with only the given lookup path.
|
||||
* @param boolean $prepend If true, push the path to the beginning of the namespace lookup paths array.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @since 3.1.4
|
||||
*/
|
||||
public static function registerNamespace($namespace, $path, $reset = false, $prepend = false)
|
||||
{
|
||||
// Verify the library path exists.
|
||||
if (!is_dir($path))
|
||||
{
|
||||
$path = (str_replace(JPATH_ROOT, '', $path) == $path) ? basename($path) : str_replace(JPATH_ROOT, '', $path);
|
||||
|
||||
throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
|
||||
}
|
||||
|
||||
// Trim leading and trailing backslashes from namespace, allowing "\Parent\Child", "Parent\Child\" and "\Parent\Child\" to be treated the same way.
|
||||
$namespace = trim($namespace, '\\');
|
||||
|
||||
// If the namespace is not yet registered or we have an explicit reset flag then set the path.
|
||||
if ($reset || !isset(self::$namespaces[$namespace]))
|
||||
{
|
||||
self::$namespaces[$namespace] = array($path);
|
||||
}
|
||||
|
||||
// Otherwise we want to simply add the path to the namespace.
|
||||
else
|
||||
{
|
||||
if ($prepend)
|
||||
{
|
||||
array_unshift(self::$namespaces[$namespace], $path);
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$namespaces[$namespace][] = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to setup the autoloaders for the Joomla Platform.
|
||||
* Since the SPL autoloaders are called in a queue we will add our explicit
|
||||
* class-registration based loader first, then fall back on the autoloader based on conventions.
|
||||
* This will allow people to register a class in a specific location and override platform libraries
|
||||
* as was previously possible.
|
||||
*
|
||||
* @param boolean $enablePsr True to enable autoloading based on PSR-0.
|
||||
* @param boolean $enablePrefixes True to enable prefix based class loading (needed to auto load the Joomla core).
|
||||
* @param boolean $enableClasses True to enable class map based class loading (needed to auto load the Joomla core).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1.4
|
||||
*/
|
||||
public static function setup($enablePsr = true, $enablePrefixes = true, $enableClasses = true)
|
||||
{
|
||||
if ($enableClasses)
|
||||
{
|
||||
// Register the class map based autoloader.
|
||||
spl_autoload_register(array('JLoader', 'load'));
|
||||
}
|
||||
|
||||
if ($enablePrefixes)
|
||||
{
|
||||
// Register the prefix autoloader.
|
||||
spl_autoload_register(array('JLoader', '_autoload'));
|
||||
}
|
||||
|
||||
if ($enablePsr)
|
||||
{
|
||||
// Register the PSR based autoloader.
|
||||
spl_autoload_register(array('JLoader', 'loadByPsr'));
|
||||
spl_autoload_register(array('JLoader', 'loadByAlias'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to autoload classes that are namespaced to the PSR-4 standard.
|
||||
*
|
||||
* @param string $class The fully qualified class name to autoload.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 3.7.0
|
||||
* @deprecated 5.0 Use JLoader::loadByPsr instead
|
||||
*/
|
||||
public static function loadByPsr4($class)
|
||||
{
|
||||
return self::loadByPsr($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to autoload classes that are namespaced to the PSR-4 standard.
|
||||
*
|
||||
* @param string $class The fully qualified class name to autoload.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function loadByPsr($class)
|
||||
{
|
||||
$class = self::stripFirstBackslash($class);
|
||||
|
||||
// Find the location of the last NS separator.
|
||||
$pos = strrpos($class, '\\');
|
||||
|
||||
// If one is found, we're dealing with a NS'd class.
|
||||
if ($pos !== false)
|
||||
{
|
||||
$classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR;
|
||||
$className = substr($class, $pos + 1);
|
||||
}
|
||||
// If not, no need to parse path.
|
||||
else
|
||||
{
|
||||
$classPath = null;
|
||||
$className = $class;
|
||||
}
|
||||
|
||||
$classPath .= $className . '.php';
|
||||
|
||||
// Loop through registered namespaces until we find a match.
|
||||
foreach (self::$namespaces as $ns => $paths)
|
||||
{
|
||||
if (strpos($class, "{$ns}\\") === 0)
|
||||
{
|
||||
$nsPath = trim(str_replace('\\', DIRECTORY_SEPARATOR, $ns), DIRECTORY_SEPARATOR);
|
||||
|
||||
// Loop through paths registered to this namespace until we find a match.
|
||||
foreach ($paths as $path)
|
||||
{
|
||||
$classFilePath = realpath($path . DIRECTORY_SEPARATOR . substr_replace($classPath, '', 0, strlen($nsPath) + 1));
|
||||
|
||||
// We do not allow files outside the namespace root to be loaded
|
||||
if (strpos($classFilePath, realpath($path)) !== 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// We check for class_exists to handle case-sensitive file systems
|
||||
if (is_file($classFilePath) && !class_exists($class, false))
|
||||
{
|
||||
$found = (bool) include_once $classFilePath;
|
||||
|
||||
if ($found)
|
||||
{
|
||||
self::loadAliasFor($class);
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to autoload classes that have been aliased using the registerAlias method.
|
||||
*
|
||||
* @param string $class The fully qualified class name to autoload.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function loadByAlias($class)
|
||||
{
|
||||
$class = strtolower(self::stripFirstBackslash($class));
|
||||
|
||||
if (isset(self::$classAliases[$class]))
|
||||
{
|
||||
// Force auto-load of the regular class
|
||||
class_exists(self::$classAliases[$class], true);
|
||||
|
||||
// Normally this shouldn't execute as the autoloader will execute applyAliasFor when the regular class is
|
||||
// auto-loaded above.
|
||||
if (!class_exists($class, false) && !interface_exists($class, false))
|
||||
{
|
||||
class_alias(self::$classAliases[$class], $class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a class alias for an already loaded class, if a class alias was created for it.
|
||||
*
|
||||
* @param string $class We'll look for and register aliases for this (real) class name
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public static function applyAliasFor($class)
|
||||
{
|
||||
$class = self::stripFirstBackslash($class);
|
||||
|
||||
if (isset(self::$classAliasesInverse[$class]))
|
||||
{
|
||||
foreach (self::$classAliasesInverse[$class] as $alias)
|
||||
{
|
||||
class_alias($class, $alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Autoload a class based on name.
|
||||
*
|
||||
* @param string $class The class to be loaded.
|
||||
*
|
||||
* @return boolean True if the class was loaded, false otherwise.
|
||||
*
|
||||
* @since 1.7.3
|
||||
*/
|
||||
public static function _autoload($class)
|
||||
{
|
||||
foreach (self::$prefixes as $prefix => $lookup)
|
||||
{
|
||||
$chr = strlen($prefix) < strlen($class) ? $class[strlen($prefix)] : 0;
|
||||
|
||||
if (strpos($class, $prefix) === 0 && ($chr === strtoupper($chr)))
|
||||
{
|
||||
return self::_load(substr($class, strlen($prefix)), $lookup);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class based on name and lookup array.
|
||||
*
|
||||
* @param string $class The class to be loaded (without prefix).
|
||||
* @param array $lookup The array of base paths to use for finding the class file.
|
||||
*
|
||||
* @return boolean True if the class was loaded, false otherwise.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
private static function _load($class, $lookup)
|
||||
{
|
||||
// Split the class name into parts separated by camelCase.
|
||||
$parts = preg_split('/(?<=[a-z0-9])(?=[A-Z])/x', $class);
|
||||
$partsCount = count($parts);
|
||||
|
||||
foreach ($lookup as $base)
|
||||
{
|
||||
// Generate the path based on the class name parts.
|
||||
$path = realpath($base . '/' . implode('/', array_map('strtolower', $parts)) . '.php');
|
||||
|
||||
// Load the file if it exists and is in the lookup path.
|
||||
if (strpos($path, realpath($base)) === 0 && is_file($path))
|
||||
{
|
||||
$found = (bool) include_once $path;
|
||||
|
||||
if ($found)
|
||||
{
|
||||
self::loadAliasFor($class);
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
// Backwards compatibility patch
|
||||
|
||||
// If there is only one part we want to duplicate that part for generating the path.
|
||||
if ($partsCount === 1)
|
||||
{
|
||||
// Generate the path based on the class name parts.
|
||||
$path = realpath($base . '/' . implode('/', array_map('strtolower', array($parts[0], $parts[0]))) . '.php');
|
||||
|
||||
// Load the file if it exists and is in the lookup path.
|
||||
if (strpos($path, realpath($base)) === 0 && is_file($path))
|
||||
{
|
||||
$found = (bool) include_once $path;
|
||||
|
||||
if ($found)
|
||||
{
|
||||
self::loadAliasFor($class);
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the aliases for the given class.
|
||||
*
|
||||
* @param string $class The class.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.8.0
|
||||
*/
|
||||
private static function loadAliasFor($class)
|
||||
{
|
||||
if (!array_key_exists($class, self::$classAliasesInverse))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (self::$classAliasesInverse[$class] as $alias)
|
||||
{
|
||||
// Force auto-load of the alias class
|
||||
class_exists($alias, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the first backslash from the given class if present.
|
||||
*
|
||||
* @param string $class The class to strip the first prefix from.
|
||||
*
|
||||
* @return string The striped class name.
|
||||
*
|
||||
* @since 3.8.0
|
||||
*/
|
||||
private static function stripFirstBackslash($class)
|
||||
{
|
||||
return $class && $class[0] === '\\' ? substr($class, 1) : $class;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if jexit is defined first (our unit tests mock this)
|
||||
if (!function_exists('jexit'))
|
||||
{
|
||||
/**
|
||||
* Global application exit.
|
||||
*
|
||||
* This function provides a single exit point for the platform.
|
||||
*
|
||||
* @param mixed $message Exit code or string. Defaults to zero.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 1.7.0
|
||||
*/
|
||||
function jexit($message = 0)
|
||||
{
|
||||
exit($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intelligent file importer.
|
||||
*
|
||||
* @param string $path A dot syntax path.
|
||||
* @param string $base Search this directory for the class.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for
|
||||
* your files.
|
||||
*/
|
||||
function jimport($path, $base = null)
|
||||
{
|
||||
return JLoader::import($path, $base);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite;
|
||||
|
||||
use Joomla\Application\AbstractWebApplication;
|
||||
use Joomla\Application\Controller\ControllerResolverInterface;
|
||||
use Joomla\Application\Web\WebClient;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\Router\RouterInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Web application class
|
||||
*/
|
||||
class WebApplication extends AbstractWebApplication
|
||||
{
|
||||
/**
|
||||
* The application's controller resolver.
|
||||
*
|
||||
* @var ControllerResolverInterface
|
||||
*/
|
||||
protected $controllerResolver;
|
||||
|
||||
/**
|
||||
* The application's router.
|
||||
*
|
||||
* @var RouterInterface
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param ControllerResolverInterface $controllerResolver The application's controller resolver
|
||||
* @param RouterInterface $router The application's router
|
||||
* @param Input $input An optional argument to provide dependency injection for the application's
|
||||
* input object.
|
||||
* @param Registry $config An optional argument to provide dependency injection for the application's
|
||||
* config object.
|
||||
* @param WebClient $client An optional argument to provide dependency injection for the application's
|
||||
* client object.
|
||||
* @param ResponseInterface $response An optional argument to provide dependency injection for the application's
|
||||
* response object.
|
||||
*/
|
||||
public function __construct(
|
||||
ControllerResolverInterface $controllerResolver,
|
||||
RouterInterface $router,
|
||||
Input $input = null,
|
||||
Registry $config = null,
|
||||
WebClient $client = null,
|
||||
ResponseInterface $response = null
|
||||
)
|
||||
{
|
||||
$this->controllerResolver = $controllerResolver;
|
||||
$this->router = $router;
|
||||
|
||||
// Call the constructor as late as possible (it runs `initialise`).
|
||||
parent::__construct($input, $config, $client, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to run the application routines.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function doExecute(): void
|
||||
{
|
||||
$route = $this->router->parseRoute($this->get('uri.route'), $this->input->getMethod());
|
||||
|
||||
// Add variables to the input if not already set
|
||||
foreach ($route->getRouteVariables() as $key => $value)
|
||||
{
|
||||
$this->input->def($key, $value);
|
||||
}
|
||||
|
||||
\call_user_func($this->controllerResolver->resolve($route));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\Application;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\CMS\User\UserFactoryInterface;
|
||||
|
||||
/**
|
||||
* Trait for application classes which are identity (user) aware
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
trait IdentityAware
|
||||
{
|
||||
/**
|
||||
* The application identity object.
|
||||
*
|
||||
* @var User
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $identity;
|
||||
|
||||
/**
|
||||
* UserFactoryInterface
|
||||
*
|
||||
* @var UserFactoryInterface
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $userFactory;
|
||||
|
||||
/**
|
||||
* Get the application identity.
|
||||
*
|
||||
* @return User
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getIdentity()
|
||||
{
|
||||
return $this->identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the application to load a custom or default identity.
|
||||
*
|
||||
* @param User $identity An optional identity object. If omitted, a null user object is created.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function loadIdentity(User $identity = null)
|
||||
{
|
||||
$this->identity = $identity ?: $this->userFactory->loadUserById(0);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user factory to use.
|
||||
*
|
||||
* @param UserFactoryInterface $userFactory The user factory to use
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function setUserFactory(UserFactoryInterface $userFactory)
|
||||
{
|
||||
$this->userFactory = $userFactory;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite;
|
||||
|
||||
use Joomla\Application\AbstractWebApplication;
|
||||
use Joomla\Application\Controller\ControllerResolverInterface;
|
||||
use Joomla\Application\Web\WebClient;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\Router\RouterInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Web application class
|
||||
*/
|
||||
class WebApplication extends AbstractWebApplication
|
||||
{
|
||||
/**
|
||||
* The application's controller resolver.
|
||||
*
|
||||
* @var ControllerResolverInterface
|
||||
*/
|
||||
protected $controllerResolver;
|
||||
|
||||
/**
|
||||
* The application's router.
|
||||
*
|
||||
* @var RouterInterface
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param ControllerResolverInterface $controllerResolver The application's controller resolver
|
||||
* @param RouterInterface $router The application's router
|
||||
* @param Input $input An optional argument to provide dependency injection for the application's
|
||||
* input object.
|
||||
* @param Registry $config An optional argument to provide dependency injection for the application's
|
||||
* config object.
|
||||
* @param WebClient $client An optional argument to provide dependency injection for the application's
|
||||
* client object.
|
||||
* @param ResponseInterface $response An optional argument to provide dependency injection for the application's
|
||||
* response object.
|
||||
*/
|
||||
public function __construct(
|
||||
ControllerResolverInterface $controllerResolver,
|
||||
RouterInterface $router,
|
||||
Input $input = null,
|
||||
Registry $config = null,
|
||||
WebClient $client = null,
|
||||
ResponseInterface $response = null
|
||||
)
|
||||
{
|
||||
$this->controllerResolver = $controllerResolver;
|
||||
$this->router = $router;
|
||||
|
||||
// Call the constructor as late as possible (it runs `initialise`).
|
||||
parent::__construct($input, $config, $client, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to run the application routines.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function doExecute(): void
|
||||
{
|
||||
$route = $this->router->parseRoute($this->get('uri.route'), $this->input->getMethod());
|
||||
|
||||
// Add variables to the input if not already set
|
||||
foreach ($route->getRouteVariables() as $key => $value)
|
||||
{
|
||||
$this->input->def($key, $value);
|
||||
}
|
||||
|
||||
\call_user_func($this->controllerResolver->resolve($route));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Asset;
|
||||
|
||||
use Symfony\Component\Asset\Context\ContextInterface;
|
||||
use Symfony\Component\Asset\Package;
|
||||
use Symfony\Component\Asset\PathPackage;
|
||||
use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;
|
||||
|
||||
/**
|
||||
* Extended path package for resolving assets from a Laravel Mix manifest
|
||||
*/
|
||||
class MixPathPackage extends PathPackage
|
||||
{
|
||||
/**
|
||||
* Decorated Package instance
|
||||
*
|
||||
* @var Package
|
||||
*/
|
||||
private $decoratedPackage;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Package $decoratedPackage Decorated Package instance
|
||||
* @param string $basePath The base path to be prepended to relative paths
|
||||
* @param VersionStrategyInterface $versionStrategy The version strategy
|
||||
* @param ContextInterface $context The context
|
||||
*/
|
||||
public function __construct(
|
||||
Package $decoratedPackage,
|
||||
string $basePath,
|
||||
VersionStrategyInterface $versionStrategy,
|
||||
ContextInterface $context = null
|
||||
) {
|
||||
parent::__construct($basePath, $versionStrategy, $context);
|
||||
|
||||
$this->decoratedPackage = $decoratedPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an absolute or root-relative public path.
|
||||
*
|
||||
* @param string $path A path
|
||||
*
|
||||
* @return string The public path
|
||||
*/
|
||||
public function getUrl($path)
|
||||
{
|
||||
if ($this->isAbsoluteUrl($path))
|
||||
{
|
||||
return $path;
|
||||
}
|
||||
|
||||
$versionedPath = $this->getVersionStrategy()->applyVersion("/$path");
|
||||
|
||||
if ($versionedPath === $path)
|
||||
{
|
||||
return $this->decoratedPackage->getUrl($path);
|
||||
}
|
||||
|
||||
return $this->getBasePath() . ltrim($versionedPath, '/');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\Autoload;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Composer\Autoload\ClassLoader as ComposerClassLoader;
|
||||
|
||||
/**
|
||||
* Decorate Composer ClassLoader for Joomla!
|
||||
*
|
||||
* For backward compatibility due to class aliasing in the CMS, the loadClass() method was modified to call
|
||||
* the JLoader::applyAliasFor() method.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/**
|
||||
* The Composer class loader
|
||||
*
|
||||
* @var ComposerClassLoader
|
||||
* @since 3.4
|
||||
*/
|
||||
private $loader;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ComposerClassLoader $loader Composer autoloader
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function __construct(ComposerClassLoader $loader)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return boolean|null True if loaded, null otherwise
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($result = $this->loader->loadClass($class))
|
||||
{
|
||||
\JLoader::applyAliasFor($class);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Controller;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\Controller\AbstractController;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageHtmlView;
|
||||
use Joomla\Input\Input;
|
||||
use Laminas\Diactoros\Response\HtmlResponse;
|
||||
|
||||
/**
|
||||
* Controller handling a package's status data listing
|
||||
*
|
||||
* @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object.
|
||||
* @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object
|
||||
*/
|
||||
class PackageController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* The view object.
|
||||
*
|
||||
* @var PackageHtmlView
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param PackageHtmlView $view The view object.
|
||||
* @param Input $input The input object.
|
||||
* @param AbstractApplication $app The application object.
|
||||
*/
|
||||
public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null)
|
||||
{
|
||||
parent::__construct($input, $app);
|
||||
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the controller.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(): bool
|
||||
{
|
||||
// Enable browser caching
|
||||
$this->getApplication()->allowCache(true);
|
||||
|
||||
$this->view->setPackage($this->getInput()->getString('package'));
|
||||
|
||||
$this->getApplication()->setResponse(new HtmlResponse($this->view->render()));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Controller;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\Controller\AbstractController;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageHtmlView;
|
||||
use Joomla\Input\Input;
|
||||
use Laminas\Diactoros\Response\HtmlResponse;
|
||||
|
||||
/**
|
||||
* Controller handling a package's status data listing
|
||||
*
|
||||
* @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object.
|
||||
* @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object
|
||||
*/
|
||||
class PackageController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* The view object.
|
||||
*
|
||||
* @var PackageHtmlView
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param PackageHtmlView $view The view object.
|
||||
* @param Input $input The input object.
|
||||
* @param AbstractApplication $app The application object.
|
||||
*/
|
||||
public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null)
|
||||
{
|
||||
parent::__construct($input, $app);
|
||||
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the controller.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(): bool
|
||||
{
|
||||
// Enable browser caching
|
||||
$this->getApplication()->allowCache(true);
|
||||
|
||||
$this->view->setPackage($this->getInput()->getString('package'));
|
||||
|
||||
$this->getApplication()->setResponse(new HtmlResponse($this->view->render()));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Controller;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\Controller\AbstractController;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageHtmlView;
|
||||
use Joomla\Input\Input;
|
||||
use Laminas\Diactoros\Response\HtmlResponse;
|
||||
|
||||
/**
|
||||
* Controller handling a package's status data listing
|
||||
*
|
||||
* @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object.
|
||||
* @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object
|
||||
*/
|
||||
class PackageController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* The view object.
|
||||
*
|
||||
* @var PackageHtmlView
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param PackageHtmlView $view The view object.
|
||||
* @param Input $input The input object.
|
||||
* @param AbstractApplication $app The application object.
|
||||
*/
|
||||
public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null)
|
||||
{
|
||||
parent::__construct($input, $app);
|
||||
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the controller.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(): bool
|
||||
{
|
||||
// Enable browser caching
|
||||
$this->getApplication()->allowCache(true);
|
||||
|
||||
$this->view->setPackage($this->getInput()->getString('package'));
|
||||
|
||||
$this->getApplication()->setResponse(new HtmlResponse($this->view->render()));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Controller;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\Controller\AbstractController;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageHtmlView;
|
||||
use Joomla\Input\Input;
|
||||
use Laminas\Diactoros\Response\HtmlResponse;
|
||||
|
||||
/**
|
||||
* Controller handling a package's status data listing
|
||||
*
|
||||
* @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object.
|
||||
* @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object
|
||||
*/
|
||||
class PackageController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* The view object.
|
||||
*
|
||||
* @var PackageHtmlView
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param PackageHtmlView $view The view object.
|
||||
* @param Input $input The input object.
|
||||
* @param AbstractApplication $app The application object.
|
||||
*/
|
||||
public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null)
|
||||
{
|
||||
parent::__construct($input, $app);
|
||||
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the controller.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(): bool
|
||||
{
|
||||
// Enable browser caching
|
||||
$this->getApplication()->allowCache(true);
|
||||
|
||||
$this->view->setPackage($this->getInput()->getString('package'));
|
||||
|
||||
$this->getApplication()->setResponse(new HtmlResponse($this->view->render()));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Controller;
|
||||
|
||||
use Joomla\Controller\AbstractController;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
|
||||
/**
|
||||
* Controller class to display a message to individuals looking for the wrong CMS
|
||||
*
|
||||
* @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object.
|
||||
* @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object
|
||||
*/
|
||||
class WrongCmsController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Execute the controller.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(): bool
|
||||
{
|
||||
// Enable browser caching
|
||||
$this->getApplication()->allowCache(true);
|
||||
|
||||
$response = new TextResponse("This isn't the CMS you're looking for.", 404);
|
||||
|
||||
$this->getApplication()->setResponse($response);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,485 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\Date;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
|
||||
/**
|
||||
* Date is a class that stores a date and provides logic to manipulate
|
||||
* and render that date in a variety of formats.
|
||||
*
|
||||
* @method Date|bool add(\DateInterval $interval) Adds an amount of days, months, years, hours, minutes and seconds to a Date object.
|
||||
* @method Date|bool sub(\DateInterval $interval) Subtracts an amount of days, months, years, hours, minutes and seconds from a Date object.
|
||||
* @method Date|bool modify(string $modify) Alter the timestamp of this object by incre/decre-menting in a format accepted by strtotime().
|
||||
*
|
||||
* @property-read string $daysinmonth t - Number of days in the given month.
|
||||
* @property-read string $dayofweek N - ISO-8601 numeric representation of the day of the week.
|
||||
* @property-read string $dayofyear z - The day of the year (starting from 0).
|
||||
* @property-read boolean $isleapyear L - Whether it's a leap year.
|
||||
* @property-read string $day d - Day of the month, 2 digits with leading zeros.
|
||||
* @property-read string $hour H - 24-hour format of an hour with leading zeros.
|
||||
* @property-read string $minute i - Minutes with leading zeros.
|
||||
* @property-read string $second s - Seconds with leading zeros.
|
||||
* @property-read string $microsecond u - Microseconds with leading zeros.
|
||||
* @property-read string $month m - Numeric representation of a month, with leading zeros.
|
||||
* @property-read string $ordinal S - English ordinal suffix for the day of the month, 2 characters.
|
||||
* @property-read string $week W - ISO-8601 week number of year, weeks starting on Monday.
|
||||
* @property-read string $year Y - A full numeric representation of a year, 4 digits.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
class Date extends \DateTime
|
||||
{
|
||||
const DAY_ABBR = "\x021\x03";
|
||||
const DAY_NAME = "\x022\x03";
|
||||
const MONTH_ABBR = "\x023\x03";
|
||||
const MONTH_NAME = "\x024\x03";
|
||||
|
||||
/**
|
||||
* The format string to be applied when using the __toString() magic method.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static $format = 'Y-m-d H:i:s';
|
||||
|
||||
/**
|
||||
* Placeholder for a \DateTimeZone object with GMT as the time zone.
|
||||
*
|
||||
* @var object
|
||||
* @since 1.7.0
|
||||
*
|
||||
* @deprecated 5.0 Without replacement
|
||||
*/
|
||||
protected static $gmt;
|
||||
|
||||
/**
|
||||
* Placeholder for a \DateTimeZone object with the default server
|
||||
* time zone as the time zone.
|
||||
*
|
||||
* @var object
|
||||
* @since 1.7.0
|
||||
*
|
||||
* @deprecated 5.0 Without replacement
|
||||
*/
|
||||
protected static $stz;
|
||||
|
||||
/**
|
||||
* The \DateTimeZone object for usage in rending dates as strings.
|
||||
*
|
||||
* @var \DateTimeZone
|
||||
* @since 3.0.0
|
||||
*/
|
||||
protected $tz;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $date String in a format accepted by strtotime(), defaults to "now".
|
||||
* @param mixed $tz Time zone to be used for the date. Might be a string or a DateTimeZone object.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function __construct($date = 'now', $tz = null)
|
||||
{
|
||||
// Create the base GMT and server time zone objects.
|
||||
if (empty(self::$gmt) || empty(self::$stz))
|
||||
{
|
||||
// @TODO: This code block stays here only for B/C, can be removed in 5.0
|
||||
self::$gmt = new \DateTimeZone('GMT');
|
||||
self::$stz = new \DateTimeZone(@date_default_timezone_get());
|
||||
}
|
||||
|
||||
// If the time zone object is not set, attempt to build it.
|
||||
if (!($tz instanceof \DateTimeZone))
|
||||
{
|
||||
if (\is_string($tz))
|
||||
{
|
||||
$tz = new \DateTimeZone($tz);
|
||||
}
|
||||
else
|
||||
{
|
||||
$tz = new \DateTimeZone('UTC');
|
||||
}
|
||||
}
|
||||
|
||||
// Backup active time zone
|
||||
$activeTZ = date_default_timezone_get();
|
||||
|
||||
// Force UTC timezone for correct time handling
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
// If the date is numeric assume a unix timestamp and convert it.
|
||||
$date = is_numeric($date) ? date('c', $date) : $date;
|
||||
|
||||
// Call the DateTime constructor.
|
||||
parent::__construct($date, $tz);
|
||||
|
||||
// Restore previously active timezone
|
||||
date_default_timezone_set($activeTZ);
|
||||
|
||||
// Set the timezone object for access later.
|
||||
$this->tz = $tz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to access properties of the date given by class to the format method.
|
||||
*
|
||||
* @param string $name The name of the property.
|
||||
*
|
||||
* @return mixed A value if the property name is valid, null otherwise.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$value = null;
|
||||
|
||||
switch ($name)
|
||||
{
|
||||
case 'daysinmonth':
|
||||
$value = $this->format('t', true);
|
||||
break;
|
||||
|
||||
case 'dayofweek':
|
||||
$value = $this->format('N', true);
|
||||
break;
|
||||
|
||||
case 'dayofyear':
|
||||
$value = $this->format('z', true);
|
||||
break;
|
||||
|
||||
case 'isleapyear':
|
||||
$value = (boolean) $this->format('L', true);
|
||||
break;
|
||||
|
||||
case 'day':
|
||||
$value = $this->format('d', true);
|
||||
break;
|
||||
|
||||
case 'hour':
|
||||
$value = $this->format('H', true);
|
||||
break;
|
||||
|
||||
case 'minute':
|
||||
$value = $this->format('i', true);
|
||||
break;
|
||||
|
||||
case 'second':
|
||||
$value = $this->format('s', true);
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
$value = $this->format('m', true);
|
||||
break;
|
||||
|
||||
case 'ordinal':
|
||||
$value = $this->format('S', true);
|
||||
break;
|
||||
|
||||
case 'week':
|
||||
$value = $this->format('W', true);
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
$value = $this->format('Y', true);
|
||||
break;
|
||||
|
||||
default:
|
||||
$trace = debug_backtrace();
|
||||
trigger_error(
|
||||
'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'],
|
||||
E_USER_NOTICE
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to render the date object in the format specified in the public
|
||||
* static member Date::$format.
|
||||
*
|
||||
* @return string The date as a formatted string.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) parent::format(self::$format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for new Date().
|
||||
*
|
||||
* @param string $date String in a format accepted by strtotime(), defaults to "now".
|
||||
* @param mixed $tz Time zone to be used for the date.
|
||||
*
|
||||
* @return Date
|
||||
*
|
||||
* @since 1.7.3
|
||||
*/
|
||||
public static function getInstance($date = 'now', $tz = null)
|
||||
{
|
||||
return new static($date, $tz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates day of week number to a string.
|
||||
*
|
||||
* @param integer $day The numeric day of the week.
|
||||
* @param boolean $abbr Return the abbreviated day string?
|
||||
*
|
||||
* @return string The day of the week.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function dayToString($day, $abbr = false)
|
||||
{
|
||||
switch ($day)
|
||||
{
|
||||
case 0:
|
||||
return $abbr ? Text::_('SUN') : Text::_('SUNDAY');
|
||||
case 1:
|
||||
return $abbr ? Text::_('MON') : Text::_('MONDAY');
|
||||
case 2:
|
||||
return $abbr ? Text::_('TUE') : Text::_('TUESDAY');
|
||||
case 3:
|
||||
return $abbr ? Text::_('WED') : Text::_('WEDNESDAY');
|
||||
case 4:
|
||||
return $abbr ? Text::_('THU') : Text::_('THURSDAY');
|
||||
case 5:
|
||||
return $abbr ? Text::_('FRI') : Text::_('FRIDAY');
|
||||
case 6:
|
||||
return $abbr ? Text::_('SAT') : Text::_('SATURDAY');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date as a formatted string in a local calendar.
|
||||
*
|
||||
* @param string $format The date format specification string (see {@link PHP_MANUAL#date})
|
||||
* @param boolean $local True to return the date string in the local time zone, false to return it in GMT.
|
||||
* @param boolean $translate True to translate localised strings
|
||||
*
|
||||
* @return string The date string in the specified format format.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function calendar($format, $local = false, $translate = true)
|
||||
{
|
||||
return $this->format($format, $local, $translate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date as a formatted string.
|
||||
*
|
||||
* @param string $format The date format specification string (see {@link PHP_MANUAL#date})
|
||||
* @param boolean $local True to return the date string in the local time zone, false to return it in GMT.
|
||||
* @param boolean $translate True to translate localised strings
|
||||
*
|
||||
* @return string The date string in the specified format format.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function format($format, $local = false, $translate = true)
|
||||
{
|
||||
if ($translate)
|
||||
{
|
||||
// Do string replacements for date format options that can be translated.
|
||||
$format = preg_replace('/(^|[^\\\])D/', "\\1" . self::DAY_ABBR, $format);
|
||||
$format = preg_replace('/(^|[^\\\])l/', "\\1" . self::DAY_NAME, $format);
|
||||
$format = preg_replace('/(^|[^\\\])M/', "\\1" . self::MONTH_ABBR, $format);
|
||||
$format = preg_replace('/(^|[^\\\])F/', "\\1" . self::MONTH_NAME, $format);
|
||||
}
|
||||
|
||||
// If the returned time should not be local use UTC.
|
||||
if ($local == false)
|
||||
{
|
||||
parent::setTimezone(new \DateTimeZone('UTC'));
|
||||
}
|
||||
|
||||
// Format the date.
|
||||
$return = parent::format($format);
|
||||
|
||||
if ($translate)
|
||||
{
|
||||
// Manually modify the month and day strings in the formatted time.
|
||||
if (strpos($return, self::DAY_ABBR) !== false)
|
||||
{
|
||||
$return = str_replace(self::DAY_ABBR, $this->dayToString(parent::format('w'), true), $return);
|
||||
}
|
||||
|
||||
if (strpos($return, self::DAY_NAME) !== false)
|
||||
{
|
||||
$return = str_replace(self::DAY_NAME, $this->dayToString(parent::format('w')), $return);
|
||||
}
|
||||
|
||||
if (strpos($return, self::MONTH_ABBR) !== false)
|
||||
{
|
||||
$return = str_replace(self::MONTH_ABBR, $this->monthToString(parent::format('n'), true), $return);
|
||||
}
|
||||
|
||||
if (strpos($return, self::MONTH_NAME) !== false)
|
||||
{
|
||||
$return = str_replace(self::MONTH_NAME, $this->monthToString(parent::format('n')), $return);
|
||||
}
|
||||
}
|
||||
|
||||
if ($local == false && $this->tz !== null)
|
||||
{
|
||||
parent::setTimezone($this->tz);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time offset from GMT in hours or seconds.
|
||||
*
|
||||
* @param boolean $hours True to return the value in hours.
|
||||
*
|
||||
* @return float The time offset from GMT either in hours or in seconds.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function getOffsetFromGmt($hours = false)
|
||||
{
|
||||
return (float) $hours ? ($this->tz->getOffset($this) / 3600) : $this->tz->getOffset($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates month number to a string.
|
||||
*
|
||||
* @param integer $month The numeric month of the year.
|
||||
* @param boolean $abbr If true, return the abbreviated month string
|
||||
*
|
||||
* @return string The month of the year.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function monthToString($month, $abbr = false)
|
||||
{
|
||||
switch ($month)
|
||||
{
|
||||
case 1:
|
||||
return $abbr ? Text::_('JANUARY_SHORT') : Text::_('JANUARY');
|
||||
case 2:
|
||||
return $abbr ? Text::_('FEBRUARY_SHORT') : Text::_('FEBRUARY');
|
||||
case 3:
|
||||
return $abbr ? Text::_('MARCH_SHORT') : Text::_('MARCH');
|
||||
case 4:
|
||||
return $abbr ? Text::_('APRIL_SHORT') : Text::_('APRIL');
|
||||
case 5:
|
||||
return $abbr ? Text::_('MAY_SHORT') : Text::_('MAY');
|
||||
case 6:
|
||||
return $abbr ? Text::_('JUNE_SHORT') : Text::_('JUNE');
|
||||
case 7:
|
||||
return $abbr ? Text::_('JULY_SHORT') : Text::_('JULY');
|
||||
case 8:
|
||||
return $abbr ? Text::_('AUGUST_SHORT') : Text::_('AUGUST');
|
||||
case 9:
|
||||
return $abbr ? Text::_('SEPTEMBER_SHORT') : Text::_('SEPTEMBER');
|
||||
case 10:
|
||||
return $abbr ? Text::_('OCTOBER_SHORT') : Text::_('OCTOBER');
|
||||
case 11:
|
||||
return $abbr ? Text::_('NOVEMBER_SHORT') : Text::_('NOVEMBER');
|
||||
case 12:
|
||||
return $abbr ? Text::_('DECEMBER_SHORT') : Text::_('DECEMBER');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to wrap the setTimezone() function and set the internal time zone object.
|
||||
*
|
||||
* @param \DateTimeZone $tz The new \DateTimeZone object.
|
||||
*
|
||||
* @return Date
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @note This method can't be type hinted due to a PHP bug: https://bugs.php.net/bug.php?id=61483
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function setTimezone($tz)
|
||||
{
|
||||
$this->tz = $tz;
|
||||
|
||||
return parent::setTimezone($tz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date as an ISO 8601 string. IETF RFC 3339 defines the ISO 8601 format
|
||||
* and it can be found at the IETF Web site.
|
||||
*
|
||||
* @param boolean $local True to return the date string in the local time zone, false to return it in GMT.
|
||||
*
|
||||
* @return string The date string in ISO 8601 format.
|
||||
*
|
||||
* @link http://www.ietf.org/rfc/rfc3339.txt
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function toISO8601($local = false)
|
||||
{
|
||||
return $this->format(\DateTimeInterface::RFC3339, $local, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date as an SQL datetime string.
|
||||
*
|
||||
* @param boolean $local True to return the date string in the local time zone, false to return it in GMT.
|
||||
* @param DatabaseDriver $db The database driver or null to use Factory::getDbo()
|
||||
*
|
||||
* @return string The date string in SQL datetime format.
|
||||
*
|
||||
* @link http://dev.mysql.com/doc/refman/5.0/en/datetime.html
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function toSql($local = false, DatabaseDriver $db = null)
|
||||
{
|
||||
if ($db === null)
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
}
|
||||
|
||||
return $this->format($db->getDateFormat(), $local, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date as an RFC 822 string. IETF RFC 2822 supercedes RFC 822 and its definition
|
||||
* can be found at the IETF Web site.
|
||||
*
|
||||
* @param boolean $local True to return the date string in the local time zone, false to return it in GMT.
|
||||
*
|
||||
* @return string The date string in RFC 822 format.
|
||||
*
|
||||
* @link http://www.ietf.org/rfc/rfc2822.txt
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function toRFC822($local = false)
|
||||
{
|
||||
return $this->format(\DateTimeInterface::RFC2822, $local, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date as UNIX time stamp.
|
||||
*
|
||||
* @return integer The date as a UNIX timestamp.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function toUnix()
|
||||
{
|
||||
return (int) parent::format('U');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\EventListener;
|
||||
|
||||
use Joomla\Application\ApplicationEvents;
|
||||
use Joomla\Application\Event\ApplicationErrorEvent;
|
||||
use Joomla\Console\ConsoleEvents;
|
||||
use Joomla\Console\Event\ApplicationErrorEvent as ConsoleApplicationErrorEvent;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
use Joomla\FrameworkWebsite\WebApplication;
|
||||
use Joomla\Renderer\RendererInterface;
|
||||
use Joomla\Router\Exception\MethodNotAllowedException;
|
||||
use Joomla\Router\Exception\RouteNotFoundException;
|
||||
use Laminas\Diactoros\Response\HtmlResponse;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Error handling event subscriber
|
||||
*/
|
||||
class ErrorSubscriber implements SubscriberInterface, LoggerAwareInterface
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Layout renderer
|
||||
*
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
|
||||
/**
|
||||
* Event subscriber constructor.
|
||||
*
|
||||
* @param RendererInterface $renderer Layout renderer
|
||||
*/
|
||||
public function __construct(RendererInterface $renderer)
|
||||
{
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of events this subscriber will listen to.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
ApplicationEvents::ERROR => 'handleWebError',
|
||||
ConsoleEvents::APPLICATION_ERROR => 'handleConsoleError',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle console application errors.
|
||||
*
|
||||
* @param ConsoleApplicationErrorEvent $event Event object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handleConsoleError(ConsoleApplicationErrorEvent $event): void
|
||||
{
|
||||
$this->logError($event->getError());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle web application errors.
|
||||
*
|
||||
* @param ApplicationErrorEvent $event Event object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handleWebError(ApplicationErrorEvent $event): void
|
||||
{
|
||||
/** @var WebApplication $app */
|
||||
$app = $event->getApplication();
|
||||
|
||||
switch (true)
|
||||
{
|
||||
case $event->getError() instanceof MethodNotAllowedException :
|
||||
// Log the error for reference
|
||||
$this->logger->error(
|
||||
sprintf('Route `%s` not supported by method `%s`', $app->get('uri.route'), $app->input->getMethod()),
|
||||
['exception' => $event->getError()]
|
||||
);
|
||||
|
||||
$this->prepareResponse($event);
|
||||
|
||||
$app->setHeader('Allow', implode(', ', $event->getError()->getAllowedMethods()));
|
||||
|
||||
break;
|
||||
|
||||
case $event->getError() instanceof RouteNotFoundException :
|
||||
// Log the error for reference
|
||||
$this->logger->error(
|
||||
sprintf('Route `%s` not found', $app->get('uri.route')),
|
||||
['exception' => $event->getError()]
|
||||
);
|
||||
|
||||
$this->prepareResponse($event);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->logError($event->getError());
|
||||
|
||||
$this->prepareResponse($event);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the error.
|
||||
*
|
||||
* @param \Throwable $throwable The error being processed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function logError(\Throwable $throwable): void
|
||||
{
|
||||
$this->logger->error(
|
||||
sprintf('Uncaught Throwable of type %s caught.', \get_class($throwable)),
|
||||
['exception' => $throwable]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the response for the event
|
||||
*
|
||||
* @param ApplicationErrorEvent $event Event object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function prepareResponse(ApplicationErrorEvent $event): void
|
||||
{
|
||||
/** @var WebApplication $app */
|
||||
$app = $event->getApplication();
|
||||
|
||||
$app->allowCache(false);
|
||||
|
||||
switch (true)
|
||||
{
|
||||
case $app->input->getString('_format', 'html') === 'json' :
|
||||
case $app->mimeType === 'application/json' :
|
||||
case $app->getResponse() instanceof JsonResponse :
|
||||
$data = [
|
||||
'code' => $event->getError()->getCode(),
|
||||
'message' => $event->getError()->getMessage(),
|
||||
'error' => true,
|
||||
];
|
||||
|
||||
$response = new JsonResponse($data);
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
$response = new HtmlResponse(
|
||||
$this->renderer->render('exception.twig', ['exception' => $event->getError()])
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
switch ($event->getError()->getCode())
|
||||
{
|
||||
case 404 :
|
||||
$response = $response->withStatus(404);
|
||||
|
||||
break;
|
||||
|
||||
case 405 :
|
||||
$response = $response->withStatus(405);
|
||||
|
||||
break;
|
||||
|
||||
case 500 :
|
||||
default :
|
||||
$response = $response->withStatus(500);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$app->setResponse($response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,850 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplicationInterface;
|
||||
use Joomla\CMS\Cache\Cache;
|
||||
use Joomla\CMS\Cache\CacheControllerFactoryInterface;
|
||||
use Joomla\CMS\Client\ClientHelper;
|
||||
use Joomla\CMS\Date\Date;
|
||||
use Joomla\CMS\Document\Document;
|
||||
use Joomla\CMS\Document\FactoryInterface;
|
||||
use Joomla\CMS\Filesystem\Stream;
|
||||
use Joomla\CMS\Language\Language;
|
||||
use Joomla\CMS\Language\LanguageFactoryInterface;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\Mail\Mail;
|
||||
use Joomla\CMS\Mail\MailHelper;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\Registry\Registry;
|
||||
use PHPMailer\PHPMailer\Exception as phpmailerException;
|
||||
|
||||
/**
|
||||
* Joomla Platform Factory class.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
abstract class Factory
|
||||
{
|
||||
/**
|
||||
* Global application object
|
||||
*
|
||||
* @var CMSApplicationInterface
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static $application = null;
|
||||
|
||||
/**
|
||||
* Global cache object
|
||||
*
|
||||
* @var Cache
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static $cache = null;
|
||||
|
||||
/**
|
||||
* Global configuration object
|
||||
*
|
||||
* @var \JConfig
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the configuration object within the application
|
||||
*/
|
||||
public static $config = null;
|
||||
|
||||
/**
|
||||
* Global container object
|
||||
*
|
||||
* @var Container
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static $container = null;
|
||||
|
||||
/**
|
||||
* Container for Date instances
|
||||
*
|
||||
* @var array
|
||||
* @since 1.7.3
|
||||
*/
|
||||
public static $dates = array();
|
||||
|
||||
/**
|
||||
* Global session object
|
||||
*
|
||||
* @var Session
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the session service in the DI container
|
||||
*/
|
||||
public static $session = null;
|
||||
|
||||
/**
|
||||
* Global language object
|
||||
*
|
||||
* @var Language
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the language service in the DI container
|
||||
*/
|
||||
public static $language = null;
|
||||
|
||||
/**
|
||||
* Global document object
|
||||
*
|
||||
* @var Document
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the document service in the DI container
|
||||
*/
|
||||
public static $document = null;
|
||||
|
||||
/**
|
||||
* Global database object
|
||||
*
|
||||
* @var DatabaseDriver
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the database service in the DI container
|
||||
*/
|
||||
public static $database = null;
|
||||
|
||||
/**
|
||||
* Global mailer object
|
||||
*
|
||||
* @var Mail
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static $mailer = null;
|
||||
|
||||
/**
|
||||
* Get the global application object. When the global application doesn't exist, an exception is thrown.
|
||||
*
|
||||
* @return CMSApplicationInterface object
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getApplication()
|
||||
{
|
||||
if (!self::$application)
|
||||
{
|
||||
throw new \Exception('Failed to start application', 500);
|
||||
}
|
||||
|
||||
return self::$application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a configuration object
|
||||
*
|
||||
* Returns the global {@link \JConfig} object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @param string $file The path to the configuration file
|
||||
* @param string $type The type of the configuration file
|
||||
* @param string $namespace The namespace of the configuration file
|
||||
*
|
||||
* @return Registry
|
||||
*
|
||||
* @see Registry
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the configuration object within the application.
|
||||
*/
|
||||
public static function getConfig($file = null, $type = 'PHP', $namespace = '')
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%s() is deprecated. The configuration object should be read from the application.',
|
||||
__METHOD__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
/**
|
||||
* If there is an application object, fetch the configuration from there.
|
||||
* Check it's not null because LanguagesModel can make it null and if it's null
|
||||
* we would want to re-init it from configuration.php.
|
||||
*/
|
||||
if (self::$application && self::$application->getConfig() !== null)
|
||||
{
|
||||
return self::$application->getConfig();
|
||||
}
|
||||
|
||||
if (!self::$config)
|
||||
{
|
||||
if ($file === null)
|
||||
{
|
||||
$file = JPATH_CONFIGURATION . '/configuration.php';
|
||||
}
|
||||
|
||||
self::$config = self::createConfig($file, $type, $namespace);
|
||||
}
|
||||
|
||||
return self::$config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a container object
|
||||
*
|
||||
* Returns the global service container object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* This method is only suggested for use in code whose responsibility is to create new services
|
||||
* and needs to be able to resolve the dependencies, and should therefore only be used when the
|
||||
* container is not accessible by other means. Valid uses of this method include:
|
||||
*
|
||||
* - A static `getInstance()` method calling a factory service from the container,
|
||||
* see `Joomla\CMS\Toolbar\Toolbar::getInstance()` as an example
|
||||
* - An application front controller loading and executing the Joomla application class,
|
||||
* see the `cli/joomla.php` file as an example
|
||||
* - Retrieving optional constructor dependencies when not injected into a class during a transitional
|
||||
* period to retain backward compatibility, in this case a deprecation notice should also be emitted to
|
||||
* notify developers of changes needed in their code
|
||||
*
|
||||
* This method is not suggested for use as a one-for-one replacement of static calls, such as
|
||||
* replacing calls to `Factory::getDbo()` with calls to `Factory::getContainer()->get('db')`, code
|
||||
* should be refactored to support dependency injection instead of making this change.
|
||||
*
|
||||
* @return Container
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getContainer(): Container
|
||||
{
|
||||
if (!self::$container)
|
||||
{
|
||||
self::$container = self::createContainer();
|
||||
}
|
||||
|
||||
return self::$container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a session object.
|
||||
*
|
||||
* Returns the global {@link Session} object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @param array $options An array containing session options
|
||||
*
|
||||
* @return Session object
|
||||
*
|
||||
* @see Session
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the session service from the dependency injection container or via $app->getSession()
|
||||
*/
|
||||
public static function getSession(array $options = array())
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the session from the dependency injection container or via %2$s::getApplication()->getSession().',
|
||||
__METHOD__,
|
||||
__CLASS__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
return self::getApplication()->getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a language object.
|
||||
*
|
||||
* Returns the global {@link Language} object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @return Language object
|
||||
*
|
||||
* @see Language
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the language service from the dependency injection container or via $app->getLanguage()
|
||||
*/
|
||||
public static function getLanguage()
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the language from the dependency injection container or via %2$s::getApplication()->getLanguage().',
|
||||
__METHOD__,
|
||||
__CLASS__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
if (!self::$language)
|
||||
{
|
||||
self::$language = self::createLanguage();
|
||||
}
|
||||
|
||||
return self::$language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a document object.
|
||||
*
|
||||
* Returns the global {@link \Joomla\CMS\Document\Document} object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @return Document object
|
||||
*
|
||||
* @see Document
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the document service from the dependency injection container or via $app->getDocument()
|
||||
*/
|
||||
public static function getDocument()
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the document from the dependency injection container or via %2$s::getApplication()->getDocument().',
|
||||
__METHOD__,
|
||||
__CLASS__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
if (!self::$document)
|
||||
{
|
||||
self::$document = self::createDocument();
|
||||
}
|
||||
|
||||
return self::$document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user object.
|
||||
*
|
||||
* Returns the global {@link User} object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @param integer $id The user to load - Can be an integer or string - If string, it is converted to ID automatically.
|
||||
*
|
||||
* @return User object
|
||||
*
|
||||
* @see User
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the user service from the dependency injection container or via $app->getIdentity()
|
||||
*/
|
||||
public static function getUser($id = null)
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the user from the dependency injection container or via %2$s::getApplication()->getIdentity().',
|
||||
__METHOD__,
|
||||
__CLASS__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
$instance = self::getApplication()->getSession()->get('user');
|
||||
|
||||
if (\is_null($id))
|
||||
{
|
||||
if (!($instance instanceof User))
|
||||
{
|
||||
$instance = User::getInstance();
|
||||
}
|
||||
}
|
||||
// Check if we have a string as the id or if the numeric id is the current instance
|
||||
elseif (!($instance instanceof User) || \is_string($id) || $instance->id !== $id)
|
||||
{
|
||||
$instance = User::getInstance($id);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cache object
|
||||
*
|
||||
* Returns the global {@link CacheController} object
|
||||
*
|
||||
* @param string $group The cache group name
|
||||
* @param string $handler The handler to use
|
||||
* @param string $storage The storage method
|
||||
*
|
||||
* @return \Joomla\CMS\Cache\CacheController object
|
||||
*
|
||||
* @see Cache
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the cache controller factory instead
|
||||
*/
|
||||
public static function getCache($group = '', $handler = 'callback', $storage = null)
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%s() is deprecated. The cache controller should be fetched from the factory.',
|
||||
__METHOD__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
$hash = md5($group . $handler . $storage);
|
||||
|
||||
if (isset(self::$cache[$hash]))
|
||||
{
|
||||
return self::$cache[$hash];
|
||||
}
|
||||
|
||||
$handler = ($handler === 'function') ? 'callback' : $handler;
|
||||
|
||||
$options = array('defaultgroup' => $group);
|
||||
|
||||
if (isset($storage))
|
||||
{
|
||||
$options['storage'] = $storage;
|
||||
}
|
||||
|
||||
$cache = self::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController($handler, $options);
|
||||
|
||||
self::$cache[$hash] = $cache;
|
||||
|
||||
return self::$cache[$hash];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a database object.
|
||||
*
|
||||
* Returns the global {@link DatabaseDriver} object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @return DatabaseDriver
|
||||
*
|
||||
* @see DatabaseDriver
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the database service from the dependency injection container
|
||||
*/
|
||||
public static function getDbo()
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the database from the dependency injection container.',
|
||||
__METHOD__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
if (!self::$database)
|
||||
{
|
||||
if (self::getContainer()->has('DatabaseDriver'))
|
||||
{
|
||||
self::$database = self::getContainer()->get('DatabaseDriver');
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$database = self::createDbo();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a mailer object.
|
||||
*
|
||||
* Returns the global {@link Mail} object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @return Mail object
|
||||
*
|
||||
* @see Mail
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static function getMailer()
|
||||
{
|
||||
if (!self::$mailer)
|
||||
{
|
||||
self::$mailer = self::createMailer();
|
||||
}
|
||||
|
||||
$copy = clone self::$mailer;
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link Date} object
|
||||
*
|
||||
* @param mixed $time The initial time for the Date object
|
||||
* @param mixed $tzOffset The timezone offset.
|
||||
*
|
||||
* @return Date object
|
||||
*
|
||||
* @see Date
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static function getDate($time = 'now', $tzOffset = null)
|
||||
{
|
||||
static $classname;
|
||||
static $mainLocale;
|
||||
|
||||
$language = self::getLanguage();
|
||||
$locale = $language->getTag();
|
||||
|
||||
if (!isset($classname) || $locale != $mainLocale)
|
||||
{
|
||||
// Store the locale for future reference
|
||||
$mainLocale = $locale;
|
||||
|
||||
if ($mainLocale !== false)
|
||||
{
|
||||
$classname = str_replace('-', '_', $mainLocale) . 'Date';
|
||||
|
||||
if (!class_exists($classname))
|
||||
{
|
||||
// The class does not exist, default to Date
|
||||
$classname = 'Joomla\\CMS\\Date\\Date';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No tag, so default to Date
|
||||
$classname = 'Joomla\\CMS\\Date\\Date';
|
||||
}
|
||||
}
|
||||
|
||||
$key = $time . '-' . ($tzOffset instanceof \DateTimeZone ? $tzOffset->getName() : (string) $tzOffset);
|
||||
|
||||
if (!isset(self::$dates[$classname][$key]))
|
||||
{
|
||||
self::$dates[$classname][$key] = new $classname($time, $tzOffset);
|
||||
}
|
||||
|
||||
$date = clone self::$dates[$classname][$key];
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a configuration object
|
||||
*
|
||||
* @param string $file The path to the configuration file.
|
||||
* @param string $type The type of the configuration file.
|
||||
* @param string $namespace The namespace of the configuration file.
|
||||
*
|
||||
* @return Registry
|
||||
*
|
||||
* @see Registry
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the configuration object within the application.
|
||||
*/
|
||||
protected static function createConfig($file, $type = 'PHP', $namespace = '')
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%s() is deprecated. The configuration object should be read from the application.',
|
||||
__METHOD__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
if (is_file($file))
|
||||
{
|
||||
include_once $file;
|
||||
}
|
||||
|
||||
// Create the registry with a default namespace of config
|
||||
$registry = new Registry;
|
||||
|
||||
// Sanitize the namespace.
|
||||
$namespace = ucfirst((string) preg_replace('/[^A-Z_]/i', '', $namespace));
|
||||
|
||||
// Build the config name.
|
||||
$name = 'JConfig' . $namespace;
|
||||
|
||||
// Handle the PHP configuration type.
|
||||
if ($type === 'PHP' && class_exists($name))
|
||||
{
|
||||
// Create the JConfig object
|
||||
$config = new $name;
|
||||
|
||||
// Load the configuration values into the registry
|
||||
$registry->loadObject($config);
|
||||
}
|
||||
|
||||
return $registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a container object
|
||||
*
|
||||
* @return Container
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected static function createContainer(): Container
|
||||
{
|
||||
$container = (new Container)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Application)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Authentication)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\CacheController)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Config)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Console)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Database)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Dispatcher)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Document)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Form)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Logger)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Language)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Menu)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Pathway)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\HTMLRegistry)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Session)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Toolbar)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\WebAssetRegistry)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\ApiRouter)
|
||||
->registerServiceProvider(new \Joomla\CMS\Service\Provider\User);
|
||||
|
||||
return $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a database object
|
||||
*
|
||||
* @return DatabaseDriver
|
||||
*
|
||||
* @see DatabaseDriver
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Use the database service in the DI container
|
||||
*/
|
||||
protected static function createDbo()
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated, register a service provider to create a %2$s instance instead.',
|
||||
__METHOD__,
|
||||
DatabaseInterface::class
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
$conf = self::getConfig();
|
||||
|
||||
$host = $conf->get('host');
|
||||
$user = $conf->get('user');
|
||||
$password = $conf->get('password');
|
||||
$database = $conf->get('db');
|
||||
$prefix = $conf->get('dbprefix');
|
||||
$driver = $conf->get('dbtype');
|
||||
|
||||
$options = array('driver' => $driver, 'host' => $host, 'user' => $user, 'password' => $password, 'database' => $database, 'prefix' => $prefix);
|
||||
|
||||
if ((int) $conf->get('dbencryption') !== 0)
|
||||
{
|
||||
$options['ssl'] = [
|
||||
'enable' => true,
|
||||
'verify_server_cert' => (bool) $conf->get('dbsslverifyservercert'),
|
||||
];
|
||||
|
||||
foreach (['cipher', 'ca', 'key', 'cert'] as $value)
|
||||
{
|
||||
$confVal = trim($conf->get('dbssl' . $value, ''));
|
||||
|
||||
if ($confVal !== '')
|
||||
{
|
||||
$options['ssl'][$value] = $confVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$db = DatabaseDriver::getInstance($options);
|
||||
}
|
||||
catch (\RuntimeException $e)
|
||||
{
|
||||
if (!headers_sent())
|
||||
{
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
|
||||
jexit('Database Error: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a mailer object
|
||||
*
|
||||
* @return Mail object
|
||||
*
|
||||
* @see Mail
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected static function createMailer()
|
||||
{
|
||||
$conf = self::getConfig();
|
||||
|
||||
$smtpauth = ($conf->get('smtpauth') == 0) ? null : 1;
|
||||
$smtpuser = $conf->get('smtpuser');
|
||||
$smtppass = $conf->get('smtppass');
|
||||
$smtphost = $conf->get('smtphost');
|
||||
$smtpsecure = $conf->get('smtpsecure');
|
||||
$smtpport = $conf->get('smtpport');
|
||||
$mailfrom = $conf->get('mailfrom');
|
||||
$fromname = $conf->get('fromname');
|
||||
$mailer = $conf->get('mailer');
|
||||
|
||||
// Create a Mail object
|
||||
$mail = Mail::getInstance();
|
||||
|
||||
// Clean the email address
|
||||
$mailfrom = MailHelper::cleanLine($mailfrom);
|
||||
|
||||
// Set default sender without Reply-to if the mailfrom is a valid address
|
||||
if (MailHelper::isEmailAddress($mailfrom))
|
||||
{
|
||||
// Wrap in try/catch to catch phpmailerExceptions if it is throwing them
|
||||
try
|
||||
{
|
||||
// Check for a false return value if exception throwing is disabled
|
||||
if ($mail->setFrom($mailfrom, MailHelper::cleanLine($fromname), false) === false)
|
||||
{
|
||||
Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail');
|
||||
}
|
||||
}
|
||||
catch (phpmailerException $e)
|
||||
{
|
||||
Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail');
|
||||
}
|
||||
}
|
||||
|
||||
// Default mailer is to use PHP's mail function
|
||||
switch ($mailer)
|
||||
{
|
||||
case 'smtp':
|
||||
$mail->useSmtp($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport);
|
||||
break;
|
||||
|
||||
case 'sendmail':
|
||||
$mail->isSendmail();
|
||||
break;
|
||||
|
||||
default:
|
||||
$mail->isMail();
|
||||
break;
|
||||
}
|
||||
|
||||
return $mail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a language object
|
||||
*
|
||||
* @return Language object
|
||||
*
|
||||
* @see Language
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the language service from the dependency injection container or via $app->getLanguage()
|
||||
*/
|
||||
protected static function createLanguage()
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the language from the dependency injection container or via %2$s::getApplication()->getLanguage().',
|
||||
__METHOD__,
|
||||
__CLASS__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
$conf = self::getConfig();
|
||||
$locale = $conf->get('language');
|
||||
$debug = $conf->get('debug_lang');
|
||||
$lang = self::getContainer()->get(LanguageFactoryInterface::class)->createLanguage($locale, $debug);
|
||||
|
||||
return $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a document object
|
||||
*
|
||||
* @return Document object
|
||||
*
|
||||
* @see Document
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the document service from the dependency injection container or via $app->getDocument()
|
||||
*/
|
||||
protected static function createDocument()
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the document from the dependency injection container or via %2$s::getApplication()->getDocument().',
|
||||
__METHOD__,
|
||||
__CLASS__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
$lang = self::getLanguage();
|
||||
|
||||
$input = self::getApplication()->input;
|
||||
$type = $input->get('format', 'html', 'cmd');
|
||||
|
||||
$version = new Version;
|
||||
|
||||
$attributes = array(
|
||||
'charset' => 'utf-8',
|
||||
'lineend' => 'unix',
|
||||
'tab' => "\t",
|
||||
'language' => $lang->getTag(),
|
||||
'direction' => $lang->isRtl() ? 'rtl' : 'ltr',
|
||||
'mediaversion' => $version->getMediaVersion(),
|
||||
);
|
||||
|
||||
return self::getContainer()->get(FactoryInterface::class)->createDocument($type, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new stream object with appropriate prefix
|
||||
*
|
||||
* @param boolean $usePrefix Prefix the connections for writing
|
||||
* @param boolean $useNetwork Use network if available for writing; use false to disable (e.g. FTP, SCP)
|
||||
* @param string $userAgentSuffix String to append to user agent
|
||||
* @param boolean $maskUserAgent User agent masking (prefix Mozilla)
|
||||
*
|
||||
* @return Stream
|
||||
*
|
||||
* @see Stream
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static function getStream($usePrefix = true, $useNetwork = true, $userAgentSuffix = 'Joomla', $maskUserAgent = false)
|
||||
{
|
||||
// Setup the context; Joomla! UA and overwrite
|
||||
$context = array();
|
||||
$version = new Version;
|
||||
|
||||
// Set the UA for HTTP and overwrite for FTP
|
||||
$context['http']['user_agent'] = $version->getUserAgent($userAgentSuffix, $maskUserAgent);
|
||||
$context['ftp']['overwrite'] = true;
|
||||
|
||||
if ($usePrefix)
|
||||
{
|
||||
$FTPOptions = ClientHelper::getCredentials('ftp');
|
||||
$SCPOptions = ClientHelper::getCredentials('scp');
|
||||
|
||||
if ($FTPOptions['enabled'] == 1 && $useNetwork)
|
||||
{
|
||||
$prefix = 'ftp://' . $FTPOptions['user'] . ':' . $FTPOptions['pass'] . '@' . $FTPOptions['host'];
|
||||
$prefix .= $FTPOptions['port'] ? ':' . $FTPOptions['port'] : '';
|
||||
$prefix .= $FTPOptions['root'];
|
||||
}
|
||||
elseif ($SCPOptions['enabled'] == 1 && $useNetwork)
|
||||
{
|
||||
$prefix = 'ssh2.sftp://' . $SCPOptions['user'] . ':' . $SCPOptions['pass'] . '@' . $SCPOptions['host'];
|
||||
$prefix .= $SCPOptions['port'] ? ':' . $SCPOptions['port'] : '';
|
||||
$prefix .= $SCPOptions['root'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$prefix = JPATH_ROOT . '/';
|
||||
}
|
||||
|
||||
$retval = new Stream($prefix, JPATH_ROOT, $context);
|
||||
}
|
||||
else
|
||||
{
|
||||
$retval = new Stream('', '', $context);
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,529 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\Filter;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\String\PunycodeHelper;
|
||||
use Joomla\Filter\InputFilter as BaseInputFilter;
|
||||
|
||||
/**
|
||||
* InputFilter is a class for filtering input from any data source
|
||||
*
|
||||
* Forked from the php input filter library by: Daniel Morris <dan@rootcube.com>
|
||||
* Original Contributors: Gianpaolo Racca, Ghislain Picard, Marco Wandschneider, Chris Tobin and Andrew Eddie.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
class InputFilter extends BaseInputFilter
|
||||
{
|
||||
/**
|
||||
* An array containing a list of extensions for files that are typically
|
||||
* executable directly in the webserver context, potentially resulting in code executions
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public const FORBIDDEN_FILE_EXTENSIONS = [
|
||||
'php', 'phps', 'pht', 'phtml', 'php3', 'php4', 'php5', 'php6', 'php7', 'asp',
|
||||
'php8', 'phar', 'inc', 'pl', 'cgi', 'fcgi', 'java', 'jar', 'py', 'aspx'
|
||||
];
|
||||
|
||||
/**
|
||||
* A flag for Unicode Supplementary Characters (4-byte Unicode character) stripping.
|
||||
*
|
||||
* @var integer
|
||||
* @since 3.5
|
||||
*/
|
||||
private $stripUSC = 0;
|
||||
|
||||
/**
|
||||
* A container for InputFilter instances.
|
||||
*
|
||||
* @var InputFilter[]
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected static $instances = array();
|
||||
/**
|
||||
* Constructor for inputFilter class. Only first parameter is required.
|
||||
*
|
||||
* @param array $tagsArray List of user-defined tags
|
||||
* @param array $attrArray List of user-defined attributes
|
||||
* @param integer $tagsMethod The constant static::ONLY_ALLOW_DEFINED_TAGS or static::BLOCK_DEFINED_TAGS
|
||||
* @param integer $attrMethod The constant static::ONLY_ALLOW_DEFINED_ATTRIBUTES or static::BLOCK_DEFINED_ATTRIBUTES
|
||||
* @param integer $xssAuto Only auto clean essentials = 0, Allow clean blocked tags/attributes = 1
|
||||
* @param integer $stripUSC Strip 4-byte unicode characters = 1, no strip = 0
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function __construct($tagsArray = array(), $attrArray = array(), $tagsMethod = 0, $attrMethod = 0, $xssAuto = 1, $stripUSC = 0)
|
||||
{
|
||||
parent::__construct($tagsArray, $attrArray, $tagsMethod, $attrMethod, $xssAuto);
|
||||
|
||||
// Assign member variables
|
||||
$this->stripUSC = $stripUSC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input filter object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @param array $tagsArray List of user-defined tags
|
||||
* @param array $attrArray List of user-defined attributes
|
||||
* @param integer $tagsMethod The constant static::ONLY_ALLOW_DEFINED_TAGS or static::BLOCK_DEFINED_TAGS
|
||||
* @param integer $attrMethod The constant static::ONLY_ALLOW_DEFINED_ATTRIBUTES or static::BLOCK_DEFINED_ATTRIBUTES
|
||||
* @param integer $xssAuto Only auto clean essentials = 0, Allow clean blocked tags/attributes = 1
|
||||
* @param integer $stripUSC Strip 4-byte unicode characters = 1, no strip = 0
|
||||
*
|
||||
* @return InputFilter The InputFilter object.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static function getInstance($tagsArray = array(), $attrArray = array(), $tagsMethod = 0, $attrMethod = 0, $xssAuto = 1, $stripUSC = 0)
|
||||
{
|
||||
$sig = md5(serialize(array($tagsArray, $attrArray, $tagsMethod, $attrMethod, $xssAuto)));
|
||||
|
||||
if (empty(self::$instances[$sig]))
|
||||
{
|
||||
self::$instances[$sig] = new InputFilter($tagsArray, $attrArray, $tagsMethod, $attrMethod, $xssAuto, $stripUSC);
|
||||
}
|
||||
|
||||
return self::$instances[$sig];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to be called by another php script. Processes for XSS and
|
||||
* specified bad code.
|
||||
*
|
||||
* @param mixed $source Input string/array-of-string to be 'cleaned'
|
||||
* @param string $type The return type for the variable:
|
||||
* INT: An integer, or an array of integers,
|
||||
* UINT: An unsigned integer, or an array of unsigned integers,
|
||||
* FLOAT: A floating point number, or an array of floating point numbers,
|
||||
* BOOLEAN: A boolean value,
|
||||
* WORD: A string containing A-Z or underscores only (not case sensitive),
|
||||
* ALNUM: A string containing A-Z or 0-9 only (not case sensitive),
|
||||
* CMD: A string containing A-Z, 0-9, underscores, periods or hyphens (not case sensitive),
|
||||
* BASE64: A string containing A-Z, 0-9, forward slashes, plus or equals (not case sensitive),
|
||||
* STRING: A fully decoded and sanitised string (default),
|
||||
* HTML: A sanitised string,
|
||||
* ARRAY: An array,
|
||||
* PATH: A sanitised file path, or an array of sanitised file paths,
|
||||
* TRIM: A string trimmed from normal, non-breaking and multibyte spaces
|
||||
* USERNAME: Do not use (use an application specific filter),
|
||||
* RAW: The raw string is returned with no filtering,
|
||||
* unknown: An unknown filter will act like STRING. If the input is an array it will return an
|
||||
* array of fully decoded and sanitised strings.
|
||||
*
|
||||
* @return mixed 'Cleaned' version of input parameter
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function clean($source, $type = 'string')
|
||||
{
|
||||
// Strip Unicode Supplementary Characters when requested to do so
|
||||
if ($this->stripUSC)
|
||||
{
|
||||
// Alternatively: preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xE2\xAF\x91", $source) but it'd be slower.
|
||||
$source = $this->stripUSC($source);
|
||||
}
|
||||
|
||||
return parent::clean($source, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to punyencode utf8 mail when saving content
|
||||
*
|
||||
* @param string $text The strings to encode
|
||||
*
|
||||
* @return string The punyencoded mail
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function emailToPunycode($text)
|
||||
{
|
||||
$pattern = '/(("mailto:)+[\w\.\-\+]+\@[^"?]+\.+[^."?]+("|\?))/';
|
||||
|
||||
if (preg_match_all($pattern, $text, $matches))
|
||||
{
|
||||
foreach ($matches[0] as $match)
|
||||
{
|
||||
$match = (string) str_replace(array('?', '"'), '', $match);
|
||||
$text = (string) str_replace($match, PunycodeHelper::emailToPunycode($match), $text);
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks an uploaded for suspicious naming and potential PHP contents which could indicate a hacking attempt.
|
||||
*
|
||||
* The options you can define are:
|
||||
* null_byte Prevent files with a null byte in their name (buffer overflow attack)
|
||||
* forbidden_extensions Do not allow these strings anywhere in the file's extension
|
||||
* php_tag_in_content Do not allow `<?php` tag in content
|
||||
* phar_stub_in_content Do not allow the `__HALT_COMPILER()` phar stub in content
|
||||
* shorttag_in_content Do not allow short tag `<?` in content
|
||||
* shorttag_extensions Which file extensions to scan for short tags in content
|
||||
* fobidden_ext_in_content Do not allow forbidden_extensions anywhere in content
|
||||
* php_ext_content_extensions Which file extensions to scan for .php in content
|
||||
*
|
||||
* This code is an adaptation and improvement of Admin Tools' UploadShield feature,
|
||||
* relicensed and contributed by its author.
|
||||
*
|
||||
* @param array $file An uploaded file descriptor
|
||||
* @param array $options The scanner options (see the code for details)
|
||||
*
|
||||
* @return boolean True of the file is safe
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public static function isSafeFile($file, $options = array())
|
||||
{
|
||||
$defaultOptions = array(
|
||||
|
||||
// Null byte in file name
|
||||
'null_byte' => true,
|
||||
|
||||
// Forbidden string in extension (e.g. php matched .php, .xxx.php, .php.xxx and so on)
|
||||
'forbidden_extensions' => self::FORBIDDEN_FILE_EXTENSIONS,
|
||||
|
||||
// <?php tag in file contents
|
||||
'php_tag_in_content' => true,
|
||||
|
||||
// <? tag in file contents
|
||||
'shorttag_in_content' => true,
|
||||
|
||||
// __HALT_COMPILER()
|
||||
'phar_stub_in_content' => true,
|
||||
|
||||
// Which file extensions to scan for short tags
|
||||
'shorttag_extensions' => array(
|
||||
'inc', 'phps', 'class', 'php3', 'php4', 'php5', 'php6', 'php7', 'php8', 'txt', 'dat', 'tpl', 'tmpl',
|
||||
),
|
||||
|
||||
// Forbidden extensions anywhere in the content
|
||||
'fobidden_ext_in_content' => true,
|
||||
|
||||
// Which file extensions to scan for .php in the content
|
||||
'php_ext_content_extensions' => array('zip', 'rar', 'tar', 'gz', 'tgz', 'bz2', 'tbz', 'jpa'),
|
||||
);
|
||||
|
||||
$options = array_merge($defaultOptions, $options);
|
||||
|
||||
// Make sure we can scan nested file descriptors
|
||||
$descriptors = $file;
|
||||
|
||||
if (isset($file['name']) && isset($file['tmp_name']))
|
||||
{
|
||||
$descriptors = static::decodeFileData(
|
||||
array(
|
||||
$file['name'],
|
||||
$file['type'],
|
||||
$file['tmp_name'],
|
||||
$file['error'],
|
||||
$file['size'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Handle non-nested descriptors (single files)
|
||||
if (isset($descriptors['name']))
|
||||
{
|
||||
$descriptors = array($descriptors);
|
||||
}
|
||||
|
||||
// Scan all descriptors detected
|
||||
foreach ($descriptors as $fileDescriptor)
|
||||
{
|
||||
if (!isset($fileDescriptor['name']))
|
||||
{
|
||||
// This is a nested descriptor. We have to recurse.
|
||||
if (!static::isSafeFile($fileDescriptor, $options))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$tempNames = $fileDescriptor['tmp_name'];
|
||||
$intendedNames = $fileDescriptor['name'];
|
||||
|
||||
if (!\is_array($tempNames))
|
||||
{
|
||||
$tempNames = array($tempNames);
|
||||
}
|
||||
|
||||
if (!\is_array($intendedNames))
|
||||
{
|
||||
$intendedNames = array($intendedNames);
|
||||
}
|
||||
|
||||
$len = \count($tempNames);
|
||||
|
||||
for ($i = 0; $i < $len; $i++)
|
||||
{
|
||||
$tempName = array_shift($tempNames);
|
||||
$intendedName = array_shift($intendedNames);
|
||||
|
||||
// 1. Null byte check
|
||||
if ($options['null_byte'])
|
||||
{
|
||||
if (strstr($intendedName, "\x00"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. PHP-in-extension check (.php, .php.xxx[.yyy[.zzz[...]]], .xxx[.yyy[.zzz[...]]].php)
|
||||
if (!empty($options['forbidden_extensions']))
|
||||
{
|
||||
$explodedName = explode('.', $intendedName);
|
||||
$explodedName = array_reverse($explodedName);
|
||||
array_pop($explodedName);
|
||||
$explodedName = array_map('strtolower', $explodedName);
|
||||
|
||||
/*
|
||||
* DO NOT USE array_intersect HERE! array_intersect expects the two arrays to
|
||||
* be set, i.e. they should have unique values.
|
||||
*/
|
||||
foreach ($options['forbidden_extensions'] as $ext)
|
||||
{
|
||||
if (\in_array($ext, $explodedName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. File contents scanner (PHP tag in file contents)
|
||||
if ($options['php_tag_in_content']
|
||||
|| $options['shorttag_in_content'] || $options['phar_stub_in_content']
|
||||
|| ($options['fobidden_ext_in_content'] && !empty($options['forbidden_extensions'])))
|
||||
{
|
||||
$fp = strlen($tempName) ? @fopen($tempName, 'r') : false;
|
||||
|
||||
if ($fp !== false)
|
||||
{
|
||||
$data = '';
|
||||
|
||||
while (!feof($fp))
|
||||
{
|
||||
$data .= @fread($fp, 131072);
|
||||
|
||||
if ($options['php_tag_in_content'] && stripos($data, '<?php') !== false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($options['phar_stub_in_content'] && stripos($data, '__HALT_COMPILER()') !== false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($options['shorttag_in_content'])
|
||||
{
|
||||
$suspiciousExtensions = $options['shorttag_extensions'];
|
||||
|
||||
if (empty($suspiciousExtensions))
|
||||
{
|
||||
$suspiciousExtensions = array(
|
||||
'inc', 'phps', 'class', 'php3', 'php4', 'txt', 'dat', 'tpl', 'tmpl',
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* DO NOT USE array_intersect HERE! array_intersect expects the two arrays to
|
||||
* be set, i.e. they should have unique values.
|
||||
*/
|
||||
$collide = false;
|
||||
|
||||
foreach ($suspiciousExtensions as $ext)
|
||||
{
|
||||
if (\in_array($ext, $explodedName))
|
||||
{
|
||||
$collide = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($collide)
|
||||
{
|
||||
// These are suspicious text files which may have the short tag (<?) in them
|
||||
if (strstr($data, '<?'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($options['fobidden_ext_in_content'] && !empty($options['forbidden_extensions']))
|
||||
{
|
||||
$suspiciousExtensions = $options['php_ext_content_extensions'];
|
||||
|
||||
if (empty($suspiciousExtensions))
|
||||
{
|
||||
$suspiciousExtensions = array(
|
||||
'zip', 'rar', 'tar', 'gz', 'tgz', 'bz2', 'tbz', 'jpa',
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* DO NOT USE array_intersect HERE! array_intersect expects the two arrays to
|
||||
* be set, i.e. they should have unique values.
|
||||
*/
|
||||
$collide = false;
|
||||
|
||||
foreach ($suspiciousExtensions as $ext)
|
||||
{
|
||||
if (\in_array($ext, $explodedName))
|
||||
{
|
||||
$collide = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($collide)
|
||||
{
|
||||
/*
|
||||
* These are suspicious text files which may have an executable
|
||||
* file extension in them
|
||||
*/
|
||||
foreach ($options['forbidden_extensions'] as $ext)
|
||||
{
|
||||
if (strstr($data, '.' . $ext))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This makes sure that we don't accidentally skip a <?php tag if it's across
|
||||
* a read boundary, even on multibyte strings
|
||||
*/
|
||||
$data = substr($data, -10);
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to decode a file data array.
|
||||
*
|
||||
* @param array $data The data array to decode.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected static function decodeFileData(array $data)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
if (\is_array($data[0]))
|
||||
{
|
||||
foreach ($data[0] as $k => $v)
|
||||
{
|
||||
$result[$k] = static::decodeFileData(array($data[0][$k], $data[1][$k], $data[2][$k], $data[3][$k], $data[4][$k]));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return array('name' => $data[0], 'type' => $data[1], 'tmp_name' => $data[2], 'error' => $data[3], 'size' => $data[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to convert to plaintext
|
||||
*
|
||||
* @param string $source The source string.
|
||||
*
|
||||
* @return string Plaintext string
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function decode($source)
|
||||
{
|
||||
static $ttr;
|
||||
|
||||
if (!\is_array($ttr))
|
||||
{
|
||||
// Entity decode
|
||||
$trans_tbl = get_html_translation_table(HTML_ENTITIES, ENT_COMPAT, 'ISO-8859-1');
|
||||
|
||||
foreach ($trans_tbl as $k => $v)
|
||||
{
|
||||
$ttr[$v] = utf8_encode($k);
|
||||
}
|
||||
}
|
||||
|
||||
$source = strtr($source, $ttr);
|
||||
|
||||
// Convert decimal
|
||||
$source = preg_replace_callback(
|
||||
'/&#(\d+);/m',
|
||||
function ($m) {
|
||||
return utf8_encode(\chr($m[1]));
|
||||
},
|
||||
$source
|
||||
);
|
||||
|
||||
// Convert hex
|
||||
$source = preg_replace_callback(
|
||||
'/&#x([a-f0-9]+);/mi',
|
||||
function ($m) {
|
||||
return utf8_encode(\chr('0x' . $m[1]));
|
||||
},
|
||||
$source
|
||||
);
|
||||
|
||||
return $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively strip Unicode Supplementary Characters from the source. Not: objects cannot be filtered.
|
||||
*
|
||||
* @param mixed $source The data to filter
|
||||
*
|
||||
* @return mixed The filtered result
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function stripUSC($source)
|
||||
{
|
||||
if (\is_object($source))
|
||||
{
|
||||
return $source;
|
||||
}
|
||||
|
||||
if (\is_array($source))
|
||||
{
|
||||
$filteredArray = array();
|
||||
|
||||
foreach ($source as $k => $v)
|
||||
{
|
||||
$filteredArray[$k] = $this->stripUSC($v);
|
||||
}
|
||||
|
||||
return $filteredArray;
|
||||
}
|
||||
|
||||
return preg_replace('/[\xF0-\xF7].../s', "\xE2\xAF\x91", $source);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Model;
|
||||
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Model\DatabaseModelInterface;
|
||||
use Joomla\Model\DatabaseModelTrait;
|
||||
|
||||
/**
|
||||
* Model class for packages
|
||||
*/
|
||||
class PackageModel implements DatabaseModelInterface
|
||||
{
|
||||
use DatabaseModelTrait;
|
||||
|
||||
/**
|
||||
* Instantiate the model.
|
||||
*
|
||||
* @param DatabaseDriver $db The database adapter.
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db)
|
||||
{
|
||||
$this->setDb($db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a package
|
||||
*
|
||||
* @param string $packageName The package name as registered with Packagist
|
||||
* @param string $displayName The package's display name
|
||||
* @param string $repoName The package's repo name
|
||||
* @param boolean $isStable Flag indicating the package is stable
|
||||
* @param boolean $isDeprecated Flag indicating the package is deprecated
|
||||
* @param boolean $isAbandoned Flag indicating the package is abandoned
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPackage(string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$data = (object) [
|
||||
'package' => $packageName,
|
||||
'display' => $displayName,
|
||||
'repo' => $repoName,
|
||||
'stable' => (int) $isStable,
|
||||
'deprecated' => (int) $isDeprecated,
|
||||
'abandoned' => (int) $isAbandoned,
|
||||
];
|
||||
|
||||
$db->insertObject('#__packages', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active package data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getActivePackages(): array
|
||||
{
|
||||
$abandoned = false;
|
||||
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__packages'))
|
||||
->where($db->quoteName('abandoned') . ' = :abandoned')
|
||||
->bind('abandoned', $abandoned, ParameterType::INTEGER);
|
||||
|
||||
return $db->setQuery($query)->loadObjectList('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a package's data
|
||||
*
|
||||
* @param string $packageName The package to lookup
|
||||
*
|
||||
* @return \stdClass
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getPackage(string $packageName): \stdClass
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__packages'))
|
||||
->where($db->quoteName('package') . ' = :package');
|
||||
|
||||
$query->bind('package', $packageName, ParameterType::STRING);
|
||||
|
||||
$package = $db->setQuery($query)->loadObject();
|
||||
|
||||
if (!$package)
|
||||
{
|
||||
throw new \RuntimeException(sprintf('Unable to find release data for the `%s` package', $package->display), 404);
|
||||
}
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the known package names
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPackageNames(): array
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select(['id', 'package'])
|
||||
->from($db->quoteName('#__packages'));
|
||||
|
||||
return $db->setQuery($query)->loadAssocList('id', 'package');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the known package data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPackages(): array
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__packages'));
|
||||
|
||||
return $db->setQuery($query)->loadObjectList('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a package
|
||||
*
|
||||
* @param integer $packageId The local package ID
|
||||
* @param string $packageName The package name as registered with Packagist
|
||||
* @param string $displayName The package's display name
|
||||
* @param string $repoName The package's repo name
|
||||
* @param boolean $isStable Flag indicating the package is stable
|
||||
* @param boolean $isDeprecated Flag indicating the package is deprecated
|
||||
* @param boolean $isAbandoned Flag indicating the package is abandoned
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updatePackage(int $packageId, string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$data = (object) [
|
||||
'id' => $packageId,
|
||||
'package' => $packageName,
|
||||
'display' => $displayName,
|
||||
'repo' => $repoName,
|
||||
'stable' => (int) $isStable,
|
||||
'deprecated' => (int) $isDeprecated,
|
||||
'abandoned' => (int) $isAbandoned,
|
||||
];
|
||||
|
||||
$db->updateObject('#__packages', $data, 'id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Model;
|
||||
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Model\DatabaseModelInterface;
|
||||
use Joomla\Model\DatabaseModelTrait;
|
||||
|
||||
/**
|
||||
* Model class for packages
|
||||
*/
|
||||
class PackageModel implements DatabaseModelInterface
|
||||
{
|
||||
use DatabaseModelTrait;
|
||||
|
||||
/**
|
||||
* Instantiate the model.
|
||||
*
|
||||
* @param DatabaseDriver $db The database adapter.
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db)
|
||||
{
|
||||
$this->setDb($db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a package
|
||||
*
|
||||
* @param string $packageName The package name as registered with Packagist
|
||||
* @param string $displayName The package's display name
|
||||
* @param string $repoName The package's repo name
|
||||
* @param boolean $isStable Flag indicating the package is stable
|
||||
* @param boolean $isDeprecated Flag indicating the package is deprecated
|
||||
* @param boolean $isAbandoned Flag indicating the package is abandoned
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPackage(string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$data = (object) [
|
||||
'package' => $packageName,
|
||||
'display' => $displayName,
|
||||
'repo' => $repoName,
|
||||
'stable' => (int) $isStable,
|
||||
'deprecated' => (int) $isDeprecated,
|
||||
'abandoned' => (int) $isAbandoned,
|
||||
];
|
||||
|
||||
$db->insertObject('#__packages', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active package data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getActivePackages(): array
|
||||
{
|
||||
$abandoned = false;
|
||||
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__packages'))
|
||||
->where($db->quoteName('abandoned') . ' = :abandoned')
|
||||
->bind('abandoned', $abandoned, ParameterType::INTEGER);
|
||||
|
||||
return $db->setQuery($query)->loadObjectList('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a package's data
|
||||
*
|
||||
* @param string $packageName The package to lookup
|
||||
*
|
||||
* @return \stdClass
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getPackage(string $packageName): \stdClass
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__packages'))
|
||||
->where($db->quoteName('package') . ' = :package');
|
||||
|
||||
$query->bind('package', $packageName, ParameterType::STRING);
|
||||
|
||||
$package = $db->setQuery($query)->loadObject();
|
||||
|
||||
if (!$package)
|
||||
{
|
||||
throw new \RuntimeException(sprintf('Unable to find release data for the `%s` package', $package->display), 404);
|
||||
}
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the known package names
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPackageNames(): array
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select(['id', 'package'])
|
||||
->from($db->quoteName('#__packages'));
|
||||
|
||||
return $db->setQuery($query)->loadAssocList('id', 'package');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the known package data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPackages(): array
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__packages'));
|
||||
|
||||
return $db->setQuery($query)->loadObjectList('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a package
|
||||
*
|
||||
* @param integer $packageId The local package ID
|
||||
* @param string $packageName The package name as registered with Packagist
|
||||
* @param string $displayName The package's display name
|
||||
* @param string $repoName The package's repo name
|
||||
* @param boolean $isStable Flag indicating the package is stable
|
||||
* @param boolean $isDeprecated Flag indicating the package is deprecated
|
||||
* @param boolean $isAbandoned Flag indicating the package is abandoned
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updatePackage(int $packageId, string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void
|
||||
{
|
||||
$db = $this->getDb();
|
||||
|
||||
$data = (object) [
|
||||
'id' => $packageId,
|
||||
'package' => $packageName,
|
||||
'display' => $displayName,
|
||||
'repo' => $repoName,
|
||||
'stable' => (int) $isStable,
|
||||
'deprecated' => (int) $isDeprecated,
|
||||
'abandoned' => (int) $isAbandoned,
|
||||
];
|
||||
|
||||
$db->updateObject('#__packages', $data, 'id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Renderer;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\Application\AbstractWebApplication;
|
||||
use Symfony\Component\Asset\Context\ContextInterface;
|
||||
|
||||
/**
|
||||
* Joomla! application aware context
|
||||
*/
|
||||
class ApplicationContext implements ContextInterface
|
||||
{
|
||||
/**
|
||||
* Application object
|
||||
*
|
||||
* @var AbstractApplication
|
||||
*/
|
||||
private $app;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param AbstractApplication $app The application object
|
||||
*/
|
||||
public function __construct(AbstractApplication $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base path.
|
||||
*
|
||||
* @return string The base path
|
||||
*/
|
||||
public function getBasePath()
|
||||
{
|
||||
return rtrim($this->app->get('uri.base.path'), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the request is secure or not.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSecure()
|
||||
{
|
||||
if ($this->app instanceof AbstractWebApplication)
|
||||
{
|
||||
return $this->app->isSslConnection();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Renderer;
|
||||
|
||||
use Symfony\Component\Asset\Packages;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Framework site's Twig extension class
|
||||
*/
|
||||
class FrameworkExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* Returns a list of filters to add to the existing list
|
||||
*
|
||||
* @return TwigFilter[] An array of TwigFilter instances
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new TwigFilter('get_class', 'get_class'),
|
||||
new TwigFilter('strip_root_path', [$this, 'stripRootPath']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
* @return TwigFunction[] An array of TwigFunction instances
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('asset', [Packages::class, 'getUrl']),
|
||||
new TwigFunction('preload', [FrameworkTwigRuntime::class, 'preloadAsset']),
|
||||
new TwigFunction('request_uri', [FrameworkTwigRuntime::class, 'getRequestUri']),
|
||||
new TwigFunction('route', [FrameworkTwigRuntime::class, 'getRouteUri']),
|
||||
new TwigFunction('sri', [FrameworkTwigRuntime::class, 'getSriAttributes'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('url', [FrameworkTwigRuntime::class, 'getRouteUrl']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the application root path defined by the constant "JPATH_ROOT"
|
||||
*
|
||||
* @param string $string The string to process
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function stripRootPath(string $string): string
|
||||
{
|
||||
return str_replace(JPATH_ROOT . DIRECTORY_SEPARATOR, '', $string);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Renderer;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\Preload\PreloadManager;
|
||||
|
||||
/**
|
||||
* Twig runtime class
|
||||
*/
|
||||
class FrameworkTwigRuntime
|
||||
{
|
||||
/**
|
||||
* Application object
|
||||
*
|
||||
* @var AbstractApplication
|
||||
*/
|
||||
private $app;
|
||||
|
||||
/**
|
||||
* The HTTP/2 preload manager
|
||||
*
|
||||
* @var PreloadManager
|
||||
*/
|
||||
private $preloadManager;
|
||||
|
||||
/**
|
||||
* The SRI manifest data
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
private $sriManifestData;
|
||||
|
||||
/**
|
||||
* The path to the SRI manifest data
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $sriManifestPath;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param AbstractApplication $app The application object
|
||||
* @param PreloadManager $preloadManager The HTTP/2 preload manager
|
||||
* @param string $sriManifestPath The path to the SRI manifest data
|
||||
*/
|
||||
public function __construct(AbstractApplication $app, PreloadManager $preloadManager, string $sriManifestPath)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->preloadManager = $preloadManager;
|
||||
$this->sriManifestPath = $sriManifestPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current URI
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequestUri(): string
|
||||
{
|
||||
return $this->app->get('uri.request');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI for a route
|
||||
*
|
||||
* @param string $route Route to get the path for
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRouteUri(string $route = ''): string
|
||||
{
|
||||
return $this->app->get('uri.base.path') . $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full URL for a route
|
||||
*
|
||||
* @param string $route Route to get the URL for
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRouteUrl(string $route = ''): string
|
||||
{
|
||||
return $this->app->get('uri.base.host') . $this->getRouteUri($route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SRI attributes for an asset
|
||||
*
|
||||
* @param string $path A public path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSriAttributes(string $path): string
|
||||
{
|
||||
if ($this->sriManifestData === null)
|
||||
{
|
||||
if (!file_exists($this->sriManifestPath))
|
||||
{
|
||||
throw new \RuntimeException(sprintf('SRI manifest file "%s" does not exist.', $this->sriManifestPath));
|
||||
}
|
||||
|
||||
$sriManifestContents = file_get_contents($this->sriManifestPath);
|
||||
|
||||
if ($sriManifestContents === false)
|
||||
{
|
||||
throw new \RuntimeException(sprintf('Could not read SRI manifest file "%s".', $this->sriManifestPath));
|
||||
}
|
||||
|
||||
$this->sriManifestData = json_decode($sriManifestContents, true);
|
||||
|
||||
if (0 < json_last_error())
|
||||
{
|
||||
throw new \RuntimeException(sprintf('Error parsing JSON from SRI manifest file "%s" - %s', $this->sriManifestPath, json_last_error_msg()));
|
||||
}
|
||||
}
|
||||
|
||||
$assetKey = "/$path";
|
||||
|
||||
if (!isset($this->sriManifestData[$assetKey]))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$attributes = '';
|
||||
|
||||
foreach ($this->sriManifestData[$assetKey] as $key => $value)
|
||||
{
|
||||
$attributes .= ' ' . $key . '="' . $value . '"';
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preload a resource
|
||||
*
|
||||
* @param string $uri The URI for the resource to preload
|
||||
* @param string $linkType The preload method to apply
|
||||
* @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)")
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function preloadAsset(string $uri, string $linkType = 'preload', array $attributes = []): string
|
||||
{
|
||||
$this->preloadManager->link($uri, $linkType, $attributes);
|
||||
|
||||
return $uri;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,748 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Service;
|
||||
|
||||
use Joomla\Application\AbstractWebApplication;
|
||||
use Joomla\Application\Controller\ContainerControllerResolver;
|
||||
use Joomla\Application\Controller\ControllerResolverInterface;
|
||||
use Joomla\Application\Web\WebClient;
|
||||
use Joomla\Console\Application as ConsoleApplication;
|
||||
use Joomla\Console\Loader\ContainerLoader;
|
||||
use Joomla\Console\Loader\LoaderInterface;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\Command\DebugEventDispatcherCommand;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\FrameworkWebsite\Command\GenerateSriCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Package\SyncCommand as PackageSyncCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Packagist\DownloadsCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Packagist\SyncCommand as PackagistSyncCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Twig\ResetCacheCommand;
|
||||
use Joomla\FrameworkWebsite\Command\UpdateCommand;
|
||||
use Joomla\FrameworkWebsite\Controller\Api\PackageControllerGet;
|
||||
use Joomla\FrameworkWebsite\Controller\Api\StatusControllerGet;
|
||||
use Joomla\FrameworkWebsite\Controller\HomepageController;
|
||||
use Joomla\FrameworkWebsite\Controller\PackageController;
|
||||
use Joomla\FrameworkWebsite\Controller\PageController;
|
||||
use Joomla\FrameworkWebsite\Controller\StatusController;
|
||||
use Joomla\FrameworkWebsite\Controller\WrongCmsController;
|
||||
use Joomla\FrameworkWebsite\Helper;
|
||||
use Joomla\FrameworkWebsite\Helper\PackagistHelper;
|
||||
use Joomla\FrameworkWebsite\Model\PackageModel;
|
||||
use Joomla\FrameworkWebsite\Model\ReleaseModel;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageHtmlView;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageJsonView;
|
||||
use Joomla\FrameworkWebsite\View\Status\StatusHtmlView;
|
||||
use Joomla\FrameworkWebsite\View\Status\StatusJsonView;
|
||||
use Joomla\FrameworkWebsite\WebApplication;
|
||||
use Joomla\Http\Http;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\Renderer\RendererInterface;
|
||||
use Joomla\Renderer\TwigRenderer;
|
||||
use Joomla\Router\Command\DebugRouterCommand;
|
||||
use Joomla\Router\Route;
|
||||
use Joomla\Router\Router;
|
||||
use Joomla\Router\RouterInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use TheIconic\Tracking\GoogleAnalytics\Analytics;
|
||||
|
||||
/**
|
||||
* Application service provider
|
||||
*/
|
||||
class ApplicationProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
/*
|
||||
* Application Classes
|
||||
*/
|
||||
|
||||
$container->share(ConsoleApplication::class, [$this, 'getConsoleApplicationService'], true);
|
||||
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(WebApplication::class, AbstractWebApplication::class)
|
||||
->share(AbstractWebApplication::class, [$this, 'getWebApplicationClassService']);
|
||||
|
||||
/*
|
||||
* Application Helpers and Dependencies
|
||||
*/
|
||||
|
||||
$container->alias(Analytics::class, 'analytics')
|
||||
->share('analytics', [$this, 'getAnalyticsService'], true);
|
||||
|
||||
$container->alias(ContainerLoader::class, LoaderInterface::class)
|
||||
->share(LoaderInterface::class, [$this, 'getCommandLoaderService'], true);
|
||||
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(ContainerControllerResolver::class, ControllerResolverInterface::class)
|
||||
->share(ControllerResolverInterface::class, [$this, 'getControllerResolverService']);
|
||||
|
||||
$container->alias(Helper::class, 'application.helper')
|
||||
->share('application.helper', [$this, 'getApplicationHelperService'], true);
|
||||
|
||||
$container->alias(PackagistHelper::class, 'application.helper.packagist')
|
||||
->share('application.helper.packagist', [$this, 'getApplicationHelperPackagistService'], true);
|
||||
|
||||
$container->share('application.packages', [$this, 'getApplicationPackagesService'], true);
|
||||
|
||||
$container->share(WebClient::class, [$this, 'getWebClientService'], true);
|
||||
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(RouterInterface::class, 'application.router')
|
||||
->alias(Router::class, 'application.router')
|
||||
->share('application.router', [$this, 'getApplicationRouterService']);
|
||||
|
||||
$container->share(Input::class, [$this, 'getInputClassService'], true);
|
||||
|
||||
/*
|
||||
* Console Commands
|
||||
*/
|
||||
|
||||
$container->share(DebugEventDispatcherCommand::class, [$this, 'getDebugEventDispatcherCommandService'], true);
|
||||
$container->share(DebugRouterCommand::class, [$this, 'getDebugRouterCommandService'], true);
|
||||
$container->share(DownloadsCommand::class, [$this, 'getDownloadsCommandService'], true);
|
||||
$container->share(GenerateSriCommand::class, [$this, 'getGenerateSriCommandService'], true);
|
||||
$container->share(PackageSyncCommand::class, [$this, 'getPackageSyncCommandService'], true);
|
||||
$container->share(PackagistSyncCommand::class, [$this, 'getPackagistSyncCommandService'], true);
|
||||
$container->share(ResetCacheCommand::class, [$this, 'getResetCacheCommandService'], true);
|
||||
$container->share(UpdateCommand::class, [$this, 'getUpdateCommandService'], true);
|
||||
|
||||
/*
|
||||
* MVC Layer
|
||||
*/
|
||||
|
||||
// Controllers
|
||||
$container->alias(PackageControllerGet::class, 'controller.api.package')
|
||||
->share('controller.api.package', [$this, 'getControllerApiPackageService'], true);
|
||||
|
||||
$container->alias(StatusControllerGet::class, 'controller.api.status')
|
||||
->share('controller.api.status', [$this, 'getControllerApiStatusService'], true);
|
||||
|
||||
$container->alias(HomepageController::class, 'controller.homepage')
|
||||
->share('controller.homepage', [$this, 'getControllerHomepageService'], true);
|
||||
|
||||
$container->alias(PackageController::class, 'controller.package')
|
||||
->share('controller.package', [$this, 'getControllerPackageService'], true);
|
||||
|
||||
$container->alias(PageController::class, 'controller.page')
|
||||
->share('controller.page', [$this, 'getControllerPageService'], true);
|
||||
|
||||
$container->alias(StatusController::class, 'controller.status')
|
||||
->share('controller.status', [$this, 'getControllerStatusService'], true);
|
||||
|
||||
$container->alias(WrongCmsController::class, 'controller.wrong.cms')
|
||||
->share('controller.wrong.cms', [$this, 'getControllerWrongCmsService'], true);
|
||||
|
||||
// Models
|
||||
$container->alias(PackageModel::class, 'model.package')
|
||||
->share('model.package', [$this, 'getModelPackageService'], true);
|
||||
|
||||
$container->alias(ReleaseModel::class, 'model.release')
|
||||
->share('model.release', [$this, 'getModelReleaseService'], true);
|
||||
|
||||
// Views
|
||||
$container->alias(PackageHtmlView::class, 'view.package.html')
|
||||
->share('view.package.html', [$this, 'getViewPackageHtmlService'], true);
|
||||
|
||||
$container->alias(PackageJsonView::class, 'view.package.json')
|
||||
->share('view.package.json', [$this, 'getViewPackageJsonService'], true);
|
||||
|
||||
$container->alias(StatusHtmlView::class, 'view.status.html')
|
||||
->share('view.status.html', [$this, 'getViewStatusHtmlService'], true);
|
||||
|
||||
$container->alias(StatusJsonView::class, 'view.status.json')
|
||||
->share('view.status.json', [$this, 'getViewStatusJsonService'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Analytics class service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Analytics
|
||||
*/
|
||||
public function getAnalyticsService(Container $container)
|
||||
{
|
||||
return new Analytics(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.helper` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Helper
|
||||
*/
|
||||
public function getApplicationHelperService(Container $container): Helper
|
||||
{
|
||||
$helper = new Helper;
|
||||
$helper->setPackages($container->get('application.packages'));
|
||||
|
||||
return $helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.helper.packagist` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackagistHelper
|
||||
*/
|
||||
public function getApplicationHelperPackagistService(Container $container): PackagistHelper
|
||||
{
|
||||
$helper = new PackagistHelper($container->get(Http::class), $container->get(DatabaseInterface::class));
|
||||
$helper->setPackages($container->get('application.packages'));
|
||||
|
||||
return $helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.packages` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Registry
|
||||
*/
|
||||
public function getApplicationPackagesService(Container $container): Registry
|
||||
{
|
||||
return (new Registry)->loadFile(JPATH_ROOT . '/packages.yml', 'YAML');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.router` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return RouterInterface
|
||||
*/
|
||||
public function getApplicationRouterService(Container $container): RouterInterface
|
||||
{
|
||||
$router = new Router;
|
||||
|
||||
/*
|
||||
* CMS Admin Panels
|
||||
*/
|
||||
$router->get(
|
||||
'/administrator',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/administrator/*',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/wp-admin',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/wp-admin/*',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'wp-login.php',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
/*
|
||||
* Web routes
|
||||
*/
|
||||
$router->addRoute(new Route(['GET', 'HEAD'], '/', HomepageController::class));
|
||||
|
||||
$router->get(
|
||||
'/status',
|
||||
StatusController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/:view',
|
||||
PageController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/status/:package',
|
||||
PackageController::class
|
||||
);
|
||||
|
||||
/*
|
||||
* API routes
|
||||
*/
|
||||
$router->get(
|
||||
'/api/v1/packages',
|
||||
StatusControllerGet::class,
|
||||
[],
|
||||
[
|
||||
'_format' => 'json',
|
||||
]
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/api/v1/packages/:package',
|
||||
PackageControllerGet::class,
|
||||
[],
|
||||
[
|
||||
'_format' => 'json',
|
||||
]
|
||||
);
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LoaderInterface service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return LoaderInterface
|
||||
*/
|
||||
public function getCommandLoaderService(Container $container): LoaderInterface
|
||||
{
|
||||
$mapping = [
|
||||
DebugEventDispatcherCommand::getDefaultName() => DebugEventDispatcherCommand::class,
|
||||
DebugRouterCommand::getDefaultName() => DebugRouterCommand::class,
|
||||
DownloadsCommand::getDefaultName() => DownloadsCommand::class,
|
||||
PackageSyncCommand::getDefaultName() => PackageSyncCommand::class,
|
||||
PackagistSyncCommand::getDefaultName() => PackagistSyncCommand::class,
|
||||
GenerateSriCommand::getDefaultName() => GenerateSriCommand::class,
|
||||
ResetCacheCommand::getDefaultName() => ResetCacheCommand::class,
|
||||
UpdateCommand::getDefaultName() => UpdateCommand::class,
|
||||
];
|
||||
|
||||
return new ContainerLoader($container, $mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ConsoleApplication service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ConsoleApplication
|
||||
*/
|
||||
public function getConsoleApplicationService(Container $container): ConsoleApplication
|
||||
{
|
||||
$application = new ConsoleApplication(new ArgvInput, new ConsoleOutput, $container->get('config'));
|
||||
|
||||
$application->setCommandLoader($container->get(LoaderInterface::class));
|
||||
$application->setDispatcher($container->get(DispatcherInterface::class));
|
||||
$application->setLogger($container->get(LoggerInterface::class));
|
||||
$application->setName('Joomla! Framework Website');
|
||||
|
||||
return $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.api.package` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageControllerGet
|
||||
*/
|
||||
public function getControllerApiPackageService(Container $container): PackageControllerGet
|
||||
{
|
||||
$controller = new PackageControllerGet(
|
||||
$container->get(PackageJsonView::class),
|
||||
$container->get(Analytics::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
|
||||
$controller->setLogger($container->get(LoggerInterface::class));
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.api.status` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusControllerGet
|
||||
*/
|
||||
public function getControllerApiStatusService(Container $container): StatusControllerGet
|
||||
{
|
||||
$controller = new StatusControllerGet(
|
||||
$container->get(StatusJsonView::class),
|
||||
$container->get(Analytics::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
|
||||
$controller->setLogger($container->get(LoggerInterface::class));
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.homepage` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return HomepageController
|
||||
*/
|
||||
public function getControllerHomepageService(Container $container): HomepageController
|
||||
{
|
||||
return new HomepageController(
|
||||
$container->get(RendererInterface::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.package` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageController
|
||||
*/
|
||||
public function getControllerPackageService(Container $container): PackageController
|
||||
{
|
||||
return new PackageController(
|
||||
$container->get(PackageHtmlView::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.page` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PageController
|
||||
*/
|
||||
public function getControllerPageService(Container $container): PageController
|
||||
{
|
||||
return new PageController(
|
||||
$container->get(RendererInterface::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the controller resolver service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ControllerResolverInterface
|
||||
*/
|
||||
public function getControllerResolverService(Container $container): ControllerResolverInterface
|
||||
{
|
||||
return new ContainerControllerResolver($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.status` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusController
|
||||
*/
|
||||
public function getControllerStatusService(Container $container): StatusController
|
||||
{
|
||||
return new StatusController(
|
||||
$container->get(StatusHtmlView::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.wrong.cms` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return WrongCmsController
|
||||
*/
|
||||
public function getControllerWrongCmsService(Container $container): WrongCmsController
|
||||
{
|
||||
return new WrongCmsController(
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DebugEventDispatcherCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DebugEventDispatcherCommand
|
||||
*/
|
||||
public function getDebugEventDispatcherCommandService(Container $container): DebugEventDispatcherCommand
|
||||
{
|
||||
return new DebugEventDispatcherCommand(
|
||||
$container->get(DispatcherInterface::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DebugRouterCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DebugRouterCommand
|
||||
*/
|
||||
public function getDebugRouterCommandService(Container $container): DebugRouterCommand
|
||||
{
|
||||
return new DebugRouterCommand(
|
||||
$container->get(Router::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DownloadsCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DownloadsCommand
|
||||
*/
|
||||
public function getDownloadsCommandService(Container $container): DownloadsCommand
|
||||
{
|
||||
return new DownloadsCommand(
|
||||
$container->get(PackagistHelper::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GenerateSriCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return GenerateSriCommand
|
||||
*/
|
||||
public function getGenerateSriCommandService(Container $container): GenerateSriCommand
|
||||
{
|
||||
return new GenerateSriCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Input class service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Input
|
||||
*/
|
||||
public function getInputClassService(Container $container): Input
|
||||
{
|
||||
return new Input($_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `model.package` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageModel
|
||||
*/
|
||||
public function getModelPackageService(Container $container): PackageModel
|
||||
{
|
||||
return new PackageModel($container->get(DatabaseInterface::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `model.release` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ReleaseModel
|
||||
*/
|
||||
public function getModelReleaseService(Container $container): ReleaseModel
|
||||
{
|
||||
return new ReleaseModel($container->get(DatabaseInterface::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PackageSyncCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageSyncCommand
|
||||
*/
|
||||
public function getPackageSyncCommandService(Container $container): PackageSyncCommand
|
||||
{
|
||||
return new PackageSyncCommand(
|
||||
$container->get(Helper::class),
|
||||
$container->get(PackageModel::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PackagistSyncCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackagistSyncCommand
|
||||
*/
|
||||
public function getPackagistSyncCommandService(Container $container): PackagistSyncCommand
|
||||
{
|
||||
return new PackagistSyncCommand(
|
||||
$container->get(Http::class),
|
||||
$container->get(PackageModel::class),
|
||||
$container->get(ReleaseModel::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ResetCacheCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ResetCacheCommand
|
||||
*/
|
||||
public function getResetCacheCommandService(Container $container): ResetCacheCommand
|
||||
{
|
||||
return new ResetCacheCommand(
|
||||
$container->get(TwigRenderer::class),
|
||||
$container->get('config')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UpdateCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return UpdateCommand
|
||||
*/
|
||||
public function getUpdateCommandService(Container $container): UpdateCommand
|
||||
{
|
||||
return new UpdateCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.package.html` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageHtmlView
|
||||
*/
|
||||
public function getViewPackageHtmlService(Container $container): PackageHtmlView
|
||||
{
|
||||
$view = new PackageHtmlView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release'),
|
||||
$container->get(Helper::class),
|
||||
$container->get('renderer')
|
||||
);
|
||||
|
||||
$view->setLayout('package.twig');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.package.json` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageJsonView
|
||||
*/
|
||||
public function getViewPackageJsonService(Container $container): PackageJsonView
|
||||
{
|
||||
return new PackageJsonView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.status.html` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusHtmlView
|
||||
*/
|
||||
public function getViewStatusHtmlService(Container $container): StatusHtmlView
|
||||
{
|
||||
$view = new StatusHtmlView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release'),
|
||||
$container->get('renderer')
|
||||
);
|
||||
|
||||
$view->setLayout('status.twig');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.status.json` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusJsonView
|
||||
*/
|
||||
public function getViewStatusJsonService(Container $container): StatusJsonView
|
||||
{
|
||||
return new StatusJsonView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WebApplication class service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return WebApplication
|
||||
*/
|
||||
public function getWebApplicationClassService(Container $container): WebApplication
|
||||
{
|
||||
$application = new WebApplication(
|
||||
$container->get(ControllerResolverInterface::class),
|
||||
$container->get(RouterInterface::class),
|
||||
$container->get(Input::class),
|
||||
$container->get('config'),
|
||||
$container->get(WebClient::class)
|
||||
);
|
||||
|
||||
$application->httpVersion = '2';
|
||||
|
||||
// Inject extra services
|
||||
$application->setDispatcher($container->get(DispatcherInterface::class));
|
||||
$application->setLogger($container->get(LoggerInterface::class));
|
||||
|
||||
return $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web client service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return WebClient
|
||||
*/
|
||||
public function getWebClientService(Container $container): WebClient
|
||||
{
|
||||
/** @var Input $input */
|
||||
$input = $container->get(Input::class);
|
||||
$userAgent = $input->server->getString('HTTP_USER_AGENT', '');
|
||||
$acceptEncoding = $input->server->getString('HTTP_ACCEPT_ENCODING', '');
|
||||
$acceptLanguage = $input->server->getString('HTTP_ACCEPT_LANGUAGE', '');
|
||||
|
||||
return new WebClient($userAgent, $acceptEncoding, $acceptLanguage);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Service;
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
/**
|
||||
* Configuration service provider
|
||||
*/
|
||||
class ConfigurationProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Configuration instance
|
||||
*
|
||||
* @var Registry
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $file Path to the config file.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct(string $file)
|
||||
{
|
||||
// Verify the configuration exists and is readable.
|
||||
if (!is_readable($file))
|
||||
{
|
||||
throw new \RuntimeException('Configuration file does not exist or is unreadable.');
|
||||
}
|
||||
|
||||
$this->config = (new Registry)->loadFile($file);
|
||||
|
||||
// Hardcode database driver option
|
||||
$this->config->set('database.driver', 'mysql');
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
$container->share(
|
||||
'config',
|
||||
function (): Registry
|
||||
{
|
||||
return $this->config;
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Service;
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\Dispatcher;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\FrameworkWebsite\EventListener\ErrorSubscriber;
|
||||
use Joomla\Renderer\RendererInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Event service provider
|
||||
*/
|
||||
class EventProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(Dispatcher::class, DispatcherInterface::class)
|
||||
->share(DispatcherInterface::class, [$this, 'getDispatcherService']);
|
||||
|
||||
$container->share(ErrorSubscriber::class, [$this, 'getErrorSubscriber'], true)
|
||||
->tag('event.subscriber', [ErrorSubscriber::class]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DispatcherInterface service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DispatcherInterface
|
||||
*/
|
||||
public function getDispatcherService(Container $container): DispatcherInterface
|
||||
{
|
||||
$dispatcher = new Dispatcher;
|
||||
|
||||
foreach ($container->getTagged('event.subscriber') as $subscriber)
|
||||
{
|
||||
$dispatcher->addSubscriber($subscriber);
|
||||
}
|
||||
|
||||
return $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ErrorSubscriber service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ErrorSubscriber
|
||||
*/
|
||||
public function getErrorSubscriber(Container $container): ErrorSubscriber
|
||||
{
|
||||
$subscriber = new ErrorSubscriber($container->get(RendererInterface::class));
|
||||
$subscriber->setLogger($container->get(LoggerInterface::class));
|
||||
|
||||
return $subscriber;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Service;
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Http\Http;
|
||||
use Joomla\Http\HttpFactory;
|
||||
|
||||
/**
|
||||
* HTTP service provider
|
||||
*/
|
||||
class HttpProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
$container->alias(Http::class, 'http')
|
||||
->share('http', [$this, 'getHttpService'], true);
|
||||
|
||||
$container->alias(HttpFactory::class, 'http.factory')
|
||||
->share('http.factory', [$this, 'getHttpFactoryService'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `http` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Http
|
||||
*/
|
||||
public function getHttpService(Container $container): Http
|
||||
{
|
||||
/** @var HttpFactory $factory */
|
||||
$factory = $container->get('http.factory');
|
||||
|
||||
return $factory->getHttp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `http.factory` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return HttpFactory
|
||||
*/
|
||||
public function getHttpFactoryService(Container $container): HttpFactory
|
||||
{
|
||||
return new HttpFactory;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Service;
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Processor\PsrLogMessageProcessor;
|
||||
use Monolog\Processor\WebProcessor;
|
||||
|
||||
/**
|
||||
* Logging service provider
|
||||
*/
|
||||
class LoggingProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
/*
|
||||
* Monolog Handlers
|
||||
*/
|
||||
$container->share('monolog.handler.application', [$this, 'getMonologHandlerApplicationService'], true);
|
||||
|
||||
/*
|
||||
* Monolog Processors
|
||||
*/
|
||||
$container->share('monolog.processor.psr3', [$this, 'getMonologProcessorPsr3Service'], true);
|
||||
$container->share('monolog.processor.web', [$this, 'getMonologProcessorWebService'], true);
|
||||
|
||||
/*
|
||||
* Application Loggers
|
||||
*/
|
||||
$container->share('monolog.logger.application.cli', [$this, 'getMonologLoggerApplicationCliService'], true);
|
||||
$container->share('monolog.logger.application.web', [$this, 'getMonologLoggerApplicationWebService'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `monolog.handler.application` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StreamHandler
|
||||
*/
|
||||
public function getMonologHandlerApplicationService(Container $container): StreamHandler
|
||||
{
|
||||
/** @var \Joomla\Registry\Registry $config */
|
||||
$config = $container->get('config');
|
||||
|
||||
$level = strtoupper($config->get('log.application', $config->get('log.level', 'error')));
|
||||
|
||||
return new StreamHandler(JPATH_ROOT . '/logs/framework.log', \constant('\\Monolog\\Logger::' . $level));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `monolog.logger.application.cli` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public function getMonologLoggerApplicationCliService(Container $container): Logger
|
||||
{
|
||||
return new Logger(
|
||||
'Framework',
|
||||
[
|
||||
$container->get('monolog.handler.application'),
|
||||
],
|
||||
[
|
||||
$container->get('monolog.processor.psr3'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `monolog.logger.application.web` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public function getMonologLoggerApplicationWebService(Container $container): Logger
|
||||
{
|
||||
return new Logger(
|
||||
'Framework',
|
||||
[
|
||||
$container->get('monolog.handler.application'),
|
||||
],
|
||||
[
|
||||
$container->get('monolog.processor.psr3'),
|
||||
$container->get('monolog.processor.web'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `monolog.processor.psr3` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PsrLogMessageProcessor
|
||||
*/
|
||||
public function getMonologProcessorPsr3Service(Container $container): PsrLogMessageProcessor
|
||||
{
|
||||
return new PsrLogMessageProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `monolog.processor.web` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return WebProcessor
|
||||
*/
|
||||
public function getMonologProcessorWebService(Container $container): WebProcessor
|
||||
{
|
||||
return new WebProcessor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,360 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\Service\Provider;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\Application\AdministratorApplication;
|
||||
use Joomla\CMS\Application\ApplicationHelper;
|
||||
use Joomla\CMS\Application\CMSApplicationInterface;
|
||||
use Joomla\CMS\Application\ConsoleApplication;
|
||||
use Joomla\CMS\Application\SiteApplication;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Installation\Application\InstallationApplication;
|
||||
use Joomla\CMS\Session\EventListener\MetadataManagerListener;
|
||||
use Joomla\CMS\Session\MetadataManager;
|
||||
use Joomla\CMS\Session\SessionFactory;
|
||||
use Joomla\CMS\Session\SessionManager;
|
||||
use Joomla\CMS\Session\Storage\JoomlaStorage;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\Exception\DependencyResolutionException;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Event\LazyServiceEventListener;
|
||||
use Joomla\Event\Priority;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\Session\HandlerInterface;
|
||||
use Joomla\Session\SessionEvents;
|
||||
use Joomla\Session\SessionInterface;
|
||||
use Joomla\Session\Storage\RuntimeStorage;
|
||||
use Joomla\Session\StorageInterface;
|
||||
|
||||
/**
|
||||
* Service provider for the application's session dependency
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Session implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->share(
|
||||
'session.web.administrator',
|
||||
function (Container $container)
|
||||
{
|
||||
/** @var Registry $config */
|
||||
$config = $container->get('config');
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Generate a session name.
|
||||
$name = ApplicationHelper::getHash($config->get('session_name', AdministratorApplication::class));
|
||||
|
||||
// Calculate the session lifetime.
|
||||
$lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900;
|
||||
|
||||
// Initialize the options for the Session object.
|
||||
$options = [
|
||||
'name' => $name,
|
||||
'expire' => $lifetime,
|
||||
];
|
||||
|
||||
if ($config->get('force_ssl') >= 1)
|
||||
{
|
||||
$options['force_ssl'] = true;
|
||||
}
|
||||
|
||||
$handler = $container->get('session.factory')->createSessionHandler($options);
|
||||
|
||||
if (!$container->has('session.handler'))
|
||||
{
|
||||
$this->registerSessionHandlerAsService($container, $handler);
|
||||
}
|
||||
|
||||
return $this->buildSession(
|
||||
new JoomlaStorage($app->input, $handler),
|
||||
$app,
|
||||
$container->get(DispatcherInterface::class),
|
||||
$options
|
||||
);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$container->share(
|
||||
'session.web.installation',
|
||||
function (Container $container)
|
||||
{
|
||||
/** @var Registry $config */
|
||||
$config = $container->get('config');
|
||||
$app = Factory::getApplication();
|
||||
|
||||
/**
|
||||
* Session handler for the session is always filesystem so it doesn't flip to the database after
|
||||
* configuration.php has been written to
|
||||
*/
|
||||
$config->set('session_handler', 'filesystem');
|
||||
|
||||
/**
|
||||
* Generate a session name - unlike all the other apps we don't have either a secret or a session name
|
||||
* (that's not the app name) until we complete installation which then leads to us dropping things like
|
||||
* language preferences after installation as the app refreshes.
|
||||
*/
|
||||
$name = md5(serialize(JPATH_ROOT . InstallationApplication::class));
|
||||
|
||||
// Calculate the session lifetime.
|
||||
$lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900;
|
||||
|
||||
// Initialize the options for the Session object.
|
||||
$options = [
|
||||
'name' => $name,
|
||||
'expire' => $lifetime,
|
||||
];
|
||||
|
||||
$handler = $container->get('session.factory')->createSessionHandler($options);
|
||||
|
||||
if (!$container->has('session.handler'))
|
||||
{
|
||||
$this->registerSessionHandlerAsService($container, $handler);
|
||||
}
|
||||
|
||||
return $this->buildSession(
|
||||
new JoomlaStorage($app->input, $handler),
|
||||
$app,
|
||||
$container->get(DispatcherInterface::class),
|
||||
$options
|
||||
);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$container->share(
|
||||
'session.web.site',
|
||||
function (Container $container)
|
||||
{
|
||||
/** @var Registry $config */
|
||||
$config = $container->get('config');
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Generate a session name.
|
||||
$name = ApplicationHelper::getHash($config->get('session_name', SiteApplication::class));
|
||||
|
||||
// Calculate the session lifetime.
|
||||
$lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900;
|
||||
|
||||
// Initialize the options for the Session object.
|
||||
$options = [
|
||||
'name' => $name,
|
||||
'expire' => $lifetime,
|
||||
];
|
||||
|
||||
if ($config->get('force_ssl') == 2)
|
||||
{
|
||||
$options['force_ssl'] = true;
|
||||
}
|
||||
|
||||
$handler = $container->get('session.factory')->createSessionHandler($options);
|
||||
|
||||
if (!$container->has('session.handler'))
|
||||
{
|
||||
$this->registerSessionHandlerAsService($container, $handler);
|
||||
}
|
||||
|
||||
return $this->buildSession(
|
||||
new JoomlaStorage($app->input, $handler),
|
||||
$app,
|
||||
$container->get(DispatcherInterface::class),
|
||||
$options
|
||||
);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$container->share(
|
||||
'session.cli',
|
||||
function (Container $container)
|
||||
{
|
||||
/** @var Registry $config */
|
||||
$config = $container->get('config');
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Generate a session name.
|
||||
$name = ApplicationHelper::getHash($config->get('session_name', ConsoleApplication::class));
|
||||
|
||||
// Calculate the session lifetime.
|
||||
$lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900;
|
||||
|
||||
// Initialize the options for the Session object.
|
||||
$options = [
|
||||
'name' => $name,
|
||||
'expire' => $lifetime,
|
||||
];
|
||||
|
||||
// Unlike the web apps, we will only toggle the force SSL setting based on it being enabled and not based on client
|
||||
if ($config->get('force_ssl') >= 1)
|
||||
{
|
||||
$options['force_ssl'] = true;
|
||||
}
|
||||
|
||||
$handler = $container->get('session.factory')->createSessionHandler($options);
|
||||
|
||||
if (!$container->has('session.handler'))
|
||||
{
|
||||
$this->registerSessionHandlerAsService($container, $handler);
|
||||
}
|
||||
|
||||
return $this->buildSession(
|
||||
new RuntimeStorage,
|
||||
$app,
|
||||
$container->get(DispatcherInterface::class),
|
||||
$options
|
||||
);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$container->alias(SessionFactory::class, 'session.factory')
|
||||
->share(
|
||||
'session.factory',
|
||||
function (Container $container)
|
||||
{
|
||||
$factory = new SessionFactory;
|
||||
$factory->setContainer($container);
|
||||
|
||||
return $factory;
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$container->alias(SessionManager::class, 'session.manager')
|
||||
->share(
|
||||
'session.manager',
|
||||
function (Container $container)
|
||||
{
|
||||
if (!$container->has('session.handler'))
|
||||
{
|
||||
throw new DependencyResolutionException(
|
||||
'The "session.handler" service has not been created, make sure you have created the "session" service first.'
|
||||
);
|
||||
}
|
||||
|
||||
return new SessionManager($container->get('session.handler'));
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$container->alias(MetadataManager::class, 'session.metadata_manager')
|
||||
->share(
|
||||
'session.metadata_manager',
|
||||
function (Container $container)
|
||||
{
|
||||
/*
|
||||
* Normally we should inject the application as a dependency via $container->get() however there is not
|
||||
* a 'app' or CMSApplicationInterface::class key for the primary application of the request so we need to
|
||||
* rely on the application having been injected to the global Factory otherwise we cannot build the service
|
||||
*/
|
||||
if (!Factory::$application)
|
||||
{
|
||||
throw new DependencyResolutionException(
|
||||
sprintf(
|
||||
'Creating the "session.metadata_manager" service requires %s::$application be initialised.',
|
||||
Factory::class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return new MetadataManager(Factory::$application, $container->get(DatabaseInterface::class));
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$container->alias(MetadataManagerListener::class, 'session.event_listener.metadata_manager')
|
||||
->share(
|
||||
'session.event_listener.metadata_manager',
|
||||
function (Container $container)
|
||||
{
|
||||
return new MetadataManagerListener($container->get(MetadataManager::class), $container->get('config'));
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$listener = new LazyServiceEventListener($container, 'session.event_listener.metadata_manager', 'onAfterSessionStart');
|
||||
|
||||
/** @var DispatcherInterface $dispatcher */
|
||||
$dispatcher = $container->get(DispatcherInterface::class);
|
||||
$dispatcher->addListener(SessionEvents::START, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the root session service
|
||||
*
|
||||
* @param StorageInterface $storage The session storage engine.
|
||||
* @param CMSApplicationInterface $app The application instance.
|
||||
* @param DispatcherInterface $dispatcher The event dispatcher.
|
||||
* @param array $options The configured session options.
|
||||
*
|
||||
* @return SessionInterface
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function buildSession(
|
||||
StorageInterface $storage,
|
||||
CMSApplicationInterface $app,
|
||||
DispatcherInterface $dispatcher,
|
||||
array $options
|
||||
): SessionInterface
|
||||
{
|
||||
$input = $app->input;
|
||||
|
||||
if (method_exists($app, 'afterSessionStart'))
|
||||
{
|
||||
$dispatcher->addListener(SessionEvents::START, [$app, 'afterSessionStart'], Priority::HIGH);
|
||||
}
|
||||
|
||||
$session = new \Joomla\CMS\Session\Session($storage, $dispatcher, $options);
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the session handler as a service
|
||||
*
|
||||
* @param Container $container The container to register the service to.
|
||||
* @param \SessionHandlerInterface $sessionHandler The session handler.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function registerSessionHandlerAsService(Container $container, \SessionHandlerInterface $sessionHandler): void
|
||||
{
|
||||
// Alias the session handler to the core SessionHandlerInterface for improved autowiring and discoverability
|
||||
$container->alias(\SessionHandlerInterface::class, 'session.handler')
|
||||
->share(
|
||||
'session.handler',
|
||||
$sessionHandler,
|
||||
true
|
||||
);
|
||||
|
||||
// If the session handler implements the extended interface, register an alias for that as well
|
||||
if ($sessionHandler instanceof HandlerInterface)
|
||||
{
|
||||
$container->alias(HandlerInterface::class, 'session.handler');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,748 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Service;
|
||||
|
||||
use Joomla\Application\AbstractWebApplication;
|
||||
use Joomla\Application\Controller\ContainerControllerResolver;
|
||||
use Joomla\Application\Controller\ControllerResolverInterface;
|
||||
use Joomla\Application\Web\WebClient;
|
||||
use Joomla\Console\Application as ConsoleApplication;
|
||||
use Joomla\Console\Loader\ContainerLoader;
|
||||
use Joomla\Console\Loader\LoaderInterface;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\Command\DebugEventDispatcherCommand;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\FrameworkWebsite\Command\GenerateSriCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Package\SyncCommand as PackageSyncCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Packagist\DownloadsCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Packagist\SyncCommand as PackagistSyncCommand;
|
||||
use Joomla\FrameworkWebsite\Command\Twig\ResetCacheCommand;
|
||||
use Joomla\FrameworkWebsite\Command\UpdateCommand;
|
||||
use Joomla\FrameworkWebsite\Controller\Api\PackageControllerGet;
|
||||
use Joomla\FrameworkWebsite\Controller\Api\StatusControllerGet;
|
||||
use Joomla\FrameworkWebsite\Controller\HomepageController;
|
||||
use Joomla\FrameworkWebsite\Controller\PackageController;
|
||||
use Joomla\FrameworkWebsite\Controller\PageController;
|
||||
use Joomla\FrameworkWebsite\Controller\StatusController;
|
||||
use Joomla\FrameworkWebsite\Controller\WrongCmsController;
|
||||
use Joomla\FrameworkWebsite\Helper;
|
||||
use Joomla\FrameworkWebsite\Helper\PackagistHelper;
|
||||
use Joomla\FrameworkWebsite\Model\PackageModel;
|
||||
use Joomla\FrameworkWebsite\Model\ReleaseModel;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageHtmlView;
|
||||
use Joomla\FrameworkWebsite\View\Package\PackageJsonView;
|
||||
use Joomla\FrameworkWebsite\View\Status\StatusHtmlView;
|
||||
use Joomla\FrameworkWebsite\View\Status\StatusJsonView;
|
||||
use Joomla\FrameworkWebsite\WebApplication;
|
||||
use Joomla\Http\Http;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\Renderer\RendererInterface;
|
||||
use Joomla\Renderer\TwigRenderer;
|
||||
use Joomla\Router\Command\DebugRouterCommand;
|
||||
use Joomla\Router\Route;
|
||||
use Joomla\Router\Router;
|
||||
use Joomla\Router\RouterInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use TheIconic\Tracking\GoogleAnalytics\Analytics;
|
||||
|
||||
/**
|
||||
* Application service provider
|
||||
*/
|
||||
class ApplicationProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
/*
|
||||
* Application Classes
|
||||
*/
|
||||
|
||||
$container->share(ConsoleApplication::class, [$this, 'getConsoleApplicationService'], true);
|
||||
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(WebApplication::class, AbstractWebApplication::class)
|
||||
->share(AbstractWebApplication::class, [$this, 'getWebApplicationClassService']);
|
||||
|
||||
/*
|
||||
* Application Helpers and Dependencies
|
||||
*/
|
||||
|
||||
$container->alias(Analytics::class, 'analytics')
|
||||
->share('analytics', [$this, 'getAnalyticsService'], true);
|
||||
|
||||
$container->alias(ContainerLoader::class, LoaderInterface::class)
|
||||
->share(LoaderInterface::class, [$this, 'getCommandLoaderService'], true);
|
||||
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(ContainerControllerResolver::class, ControllerResolverInterface::class)
|
||||
->share(ControllerResolverInterface::class, [$this, 'getControllerResolverService']);
|
||||
|
||||
$container->alias(Helper::class, 'application.helper')
|
||||
->share('application.helper', [$this, 'getApplicationHelperService'], true);
|
||||
|
||||
$container->alias(PackagistHelper::class, 'application.helper.packagist')
|
||||
->share('application.helper.packagist', [$this, 'getApplicationHelperPackagistService'], true);
|
||||
|
||||
$container->share('application.packages', [$this, 'getApplicationPackagesService'], true);
|
||||
|
||||
$container->share(WebClient::class, [$this, 'getWebClientService'], true);
|
||||
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(RouterInterface::class, 'application.router')
|
||||
->alias(Router::class, 'application.router')
|
||||
->share('application.router', [$this, 'getApplicationRouterService']);
|
||||
|
||||
$container->share(Input::class, [$this, 'getInputClassService'], true);
|
||||
|
||||
/*
|
||||
* Console Commands
|
||||
*/
|
||||
|
||||
$container->share(DebugEventDispatcherCommand::class, [$this, 'getDebugEventDispatcherCommandService'], true);
|
||||
$container->share(DebugRouterCommand::class, [$this, 'getDebugRouterCommandService'], true);
|
||||
$container->share(DownloadsCommand::class, [$this, 'getDownloadsCommandService'], true);
|
||||
$container->share(GenerateSriCommand::class, [$this, 'getGenerateSriCommandService'], true);
|
||||
$container->share(PackageSyncCommand::class, [$this, 'getPackageSyncCommandService'], true);
|
||||
$container->share(PackagistSyncCommand::class, [$this, 'getPackagistSyncCommandService'], true);
|
||||
$container->share(ResetCacheCommand::class, [$this, 'getResetCacheCommandService'], true);
|
||||
$container->share(UpdateCommand::class, [$this, 'getUpdateCommandService'], true);
|
||||
|
||||
/*
|
||||
* MVC Layer
|
||||
*/
|
||||
|
||||
// Controllers
|
||||
$container->alias(PackageControllerGet::class, 'controller.api.package')
|
||||
->share('controller.api.package', [$this, 'getControllerApiPackageService'], true);
|
||||
|
||||
$container->alias(StatusControllerGet::class, 'controller.api.status')
|
||||
->share('controller.api.status', [$this, 'getControllerApiStatusService'], true);
|
||||
|
||||
$container->alias(HomepageController::class, 'controller.homepage')
|
||||
->share('controller.homepage', [$this, 'getControllerHomepageService'], true);
|
||||
|
||||
$container->alias(PackageController::class, 'controller.package')
|
||||
->share('controller.package', [$this, 'getControllerPackageService'], true);
|
||||
|
||||
$container->alias(PageController::class, 'controller.page')
|
||||
->share('controller.page', [$this, 'getControllerPageService'], true);
|
||||
|
||||
$container->alias(StatusController::class, 'controller.status')
|
||||
->share('controller.status', [$this, 'getControllerStatusService'], true);
|
||||
|
||||
$container->alias(WrongCmsController::class, 'controller.wrong.cms')
|
||||
->share('controller.wrong.cms', [$this, 'getControllerWrongCmsService'], true);
|
||||
|
||||
// Models
|
||||
$container->alias(PackageModel::class, 'model.package')
|
||||
->share('model.package', [$this, 'getModelPackageService'], true);
|
||||
|
||||
$container->alias(ReleaseModel::class, 'model.release')
|
||||
->share('model.release', [$this, 'getModelReleaseService'], true);
|
||||
|
||||
// Views
|
||||
$container->alias(PackageHtmlView::class, 'view.package.html')
|
||||
->share('view.package.html', [$this, 'getViewPackageHtmlService'], true);
|
||||
|
||||
$container->alias(PackageJsonView::class, 'view.package.json')
|
||||
->share('view.package.json', [$this, 'getViewPackageJsonService'], true);
|
||||
|
||||
$container->alias(StatusHtmlView::class, 'view.status.html')
|
||||
->share('view.status.html', [$this, 'getViewStatusHtmlService'], true);
|
||||
|
||||
$container->alias(StatusJsonView::class, 'view.status.json')
|
||||
->share('view.status.json', [$this, 'getViewStatusJsonService'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Analytics class service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Analytics
|
||||
*/
|
||||
public function getAnalyticsService(Container $container)
|
||||
{
|
||||
return new Analytics(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.helper` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Helper
|
||||
*/
|
||||
public function getApplicationHelperService(Container $container): Helper
|
||||
{
|
||||
$helper = new Helper;
|
||||
$helper->setPackages($container->get('application.packages'));
|
||||
|
||||
return $helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.helper.packagist` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackagistHelper
|
||||
*/
|
||||
public function getApplicationHelperPackagistService(Container $container): PackagistHelper
|
||||
{
|
||||
$helper = new PackagistHelper($container->get(Http::class), $container->get(DatabaseInterface::class));
|
||||
$helper->setPackages($container->get('application.packages'));
|
||||
|
||||
return $helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.packages` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Registry
|
||||
*/
|
||||
public function getApplicationPackagesService(Container $container): Registry
|
||||
{
|
||||
return (new Registry)->loadFile(JPATH_ROOT . '/packages.yml', 'YAML');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `application.router` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return RouterInterface
|
||||
*/
|
||||
public function getApplicationRouterService(Container $container): RouterInterface
|
||||
{
|
||||
$router = new Router;
|
||||
|
||||
/*
|
||||
* CMS Admin Panels
|
||||
*/
|
||||
$router->get(
|
||||
'/administrator',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/administrator/*',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/wp-admin',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/wp-admin/*',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'wp-login.php',
|
||||
WrongCmsController::class
|
||||
);
|
||||
|
||||
/*
|
||||
* Web routes
|
||||
*/
|
||||
$router->addRoute(new Route(['GET', 'HEAD'], '/', HomepageController::class));
|
||||
|
||||
$router->get(
|
||||
'/status',
|
||||
StatusController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/:view',
|
||||
PageController::class
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/status/:package',
|
||||
PackageController::class
|
||||
);
|
||||
|
||||
/*
|
||||
* API routes
|
||||
*/
|
||||
$router->get(
|
||||
'/api/v1/packages',
|
||||
StatusControllerGet::class,
|
||||
[],
|
||||
[
|
||||
'_format' => 'json',
|
||||
]
|
||||
);
|
||||
|
||||
$router->get(
|
||||
'/api/v1/packages/:package',
|
||||
PackageControllerGet::class,
|
||||
[],
|
||||
[
|
||||
'_format' => 'json',
|
||||
]
|
||||
);
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LoaderInterface service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return LoaderInterface
|
||||
*/
|
||||
public function getCommandLoaderService(Container $container): LoaderInterface
|
||||
{
|
||||
$mapping = [
|
||||
DebugEventDispatcherCommand::getDefaultName() => DebugEventDispatcherCommand::class,
|
||||
DebugRouterCommand::getDefaultName() => DebugRouterCommand::class,
|
||||
DownloadsCommand::getDefaultName() => DownloadsCommand::class,
|
||||
PackageSyncCommand::getDefaultName() => PackageSyncCommand::class,
|
||||
PackagistSyncCommand::getDefaultName() => PackagistSyncCommand::class,
|
||||
GenerateSriCommand::getDefaultName() => GenerateSriCommand::class,
|
||||
ResetCacheCommand::getDefaultName() => ResetCacheCommand::class,
|
||||
UpdateCommand::getDefaultName() => UpdateCommand::class,
|
||||
];
|
||||
|
||||
return new ContainerLoader($container, $mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ConsoleApplication service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ConsoleApplication
|
||||
*/
|
||||
public function getConsoleApplicationService(Container $container): ConsoleApplication
|
||||
{
|
||||
$application = new ConsoleApplication(new ArgvInput, new ConsoleOutput, $container->get('config'));
|
||||
|
||||
$application->setCommandLoader($container->get(LoaderInterface::class));
|
||||
$application->setDispatcher($container->get(DispatcherInterface::class));
|
||||
$application->setLogger($container->get(LoggerInterface::class));
|
||||
$application->setName('Joomla! Framework Website');
|
||||
|
||||
return $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.api.package` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageControllerGet
|
||||
*/
|
||||
public function getControllerApiPackageService(Container $container): PackageControllerGet
|
||||
{
|
||||
$controller = new PackageControllerGet(
|
||||
$container->get(PackageJsonView::class),
|
||||
$container->get(Analytics::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
|
||||
$controller->setLogger($container->get(LoggerInterface::class));
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.api.status` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusControllerGet
|
||||
*/
|
||||
public function getControllerApiStatusService(Container $container): StatusControllerGet
|
||||
{
|
||||
$controller = new StatusControllerGet(
|
||||
$container->get(StatusJsonView::class),
|
||||
$container->get(Analytics::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
|
||||
$controller->setLogger($container->get(LoggerInterface::class));
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.homepage` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return HomepageController
|
||||
*/
|
||||
public function getControllerHomepageService(Container $container): HomepageController
|
||||
{
|
||||
return new HomepageController(
|
||||
$container->get(RendererInterface::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.package` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageController
|
||||
*/
|
||||
public function getControllerPackageService(Container $container): PackageController
|
||||
{
|
||||
return new PackageController(
|
||||
$container->get(PackageHtmlView::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.page` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PageController
|
||||
*/
|
||||
public function getControllerPageService(Container $container): PageController
|
||||
{
|
||||
return new PageController(
|
||||
$container->get(RendererInterface::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the controller resolver service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ControllerResolverInterface
|
||||
*/
|
||||
public function getControllerResolverService(Container $container): ControllerResolverInterface
|
||||
{
|
||||
return new ContainerControllerResolver($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.status` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusController
|
||||
*/
|
||||
public function getControllerStatusService(Container $container): StatusController
|
||||
{
|
||||
return new StatusController(
|
||||
$container->get(StatusHtmlView::class),
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `controller.wrong.cms` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return WrongCmsController
|
||||
*/
|
||||
public function getControllerWrongCmsService(Container $container): WrongCmsController
|
||||
{
|
||||
return new WrongCmsController(
|
||||
$container->get(Input::class),
|
||||
$container->get(WebApplication::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DebugEventDispatcherCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DebugEventDispatcherCommand
|
||||
*/
|
||||
public function getDebugEventDispatcherCommandService(Container $container): DebugEventDispatcherCommand
|
||||
{
|
||||
return new DebugEventDispatcherCommand(
|
||||
$container->get(DispatcherInterface::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DebugRouterCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DebugRouterCommand
|
||||
*/
|
||||
public function getDebugRouterCommandService(Container $container): DebugRouterCommand
|
||||
{
|
||||
return new DebugRouterCommand(
|
||||
$container->get(Router::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DownloadsCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DownloadsCommand
|
||||
*/
|
||||
public function getDownloadsCommandService(Container $container): DownloadsCommand
|
||||
{
|
||||
return new DownloadsCommand(
|
||||
$container->get(PackagistHelper::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GenerateSriCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return GenerateSriCommand
|
||||
*/
|
||||
public function getGenerateSriCommandService(Container $container): GenerateSriCommand
|
||||
{
|
||||
return new GenerateSriCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Input class service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Input
|
||||
*/
|
||||
public function getInputClassService(Container $container): Input
|
||||
{
|
||||
return new Input($_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `model.package` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageModel
|
||||
*/
|
||||
public function getModelPackageService(Container $container): PackageModel
|
||||
{
|
||||
return new PackageModel($container->get(DatabaseInterface::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `model.release` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ReleaseModel
|
||||
*/
|
||||
public function getModelReleaseService(Container $container): ReleaseModel
|
||||
{
|
||||
return new ReleaseModel($container->get(DatabaseInterface::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PackageSyncCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageSyncCommand
|
||||
*/
|
||||
public function getPackageSyncCommandService(Container $container): PackageSyncCommand
|
||||
{
|
||||
return new PackageSyncCommand(
|
||||
$container->get(Helper::class),
|
||||
$container->get(PackageModel::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PackagistSyncCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackagistSyncCommand
|
||||
*/
|
||||
public function getPackagistSyncCommandService(Container $container): PackagistSyncCommand
|
||||
{
|
||||
return new PackagistSyncCommand(
|
||||
$container->get(Http::class),
|
||||
$container->get(PackageModel::class),
|
||||
$container->get(ReleaseModel::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ResetCacheCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ResetCacheCommand
|
||||
*/
|
||||
public function getResetCacheCommandService(Container $container): ResetCacheCommand
|
||||
{
|
||||
return new ResetCacheCommand(
|
||||
$container->get(TwigRenderer::class),
|
||||
$container->get('config')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UpdateCommand service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return UpdateCommand
|
||||
*/
|
||||
public function getUpdateCommandService(Container $container): UpdateCommand
|
||||
{
|
||||
return new UpdateCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.package.html` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageHtmlView
|
||||
*/
|
||||
public function getViewPackageHtmlService(Container $container): PackageHtmlView
|
||||
{
|
||||
$view = new PackageHtmlView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release'),
|
||||
$container->get(Helper::class),
|
||||
$container->get('renderer')
|
||||
);
|
||||
|
||||
$view->setLayout('package.twig');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.package.json` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return PackageJsonView
|
||||
*/
|
||||
public function getViewPackageJsonService(Container $container): PackageJsonView
|
||||
{
|
||||
return new PackageJsonView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.status.html` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusHtmlView
|
||||
*/
|
||||
public function getViewStatusHtmlService(Container $container): StatusHtmlView
|
||||
{
|
||||
$view = new StatusHtmlView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release'),
|
||||
$container->get('renderer')
|
||||
);
|
||||
|
||||
$view->setLayout('status.twig');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `view.status.json` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return StatusJsonView
|
||||
*/
|
||||
public function getViewStatusJsonService(Container $container): StatusJsonView
|
||||
{
|
||||
return new StatusJsonView(
|
||||
$container->get('model.package'),
|
||||
$container->get('model.release')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WebApplication class service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return WebApplication
|
||||
*/
|
||||
public function getWebApplicationClassService(Container $container): WebApplication
|
||||
{
|
||||
$application = new WebApplication(
|
||||
$container->get(ControllerResolverInterface::class),
|
||||
$container->get(RouterInterface::class),
|
||||
$container->get(Input::class),
|
||||
$container->get('config'),
|
||||
$container->get(WebClient::class)
|
||||
);
|
||||
|
||||
$application->httpVersion = '2';
|
||||
|
||||
// Inject extra services
|
||||
$application->setDispatcher($container->get(DispatcherInterface::class));
|
||||
$application->setLogger($container->get(LoggerInterface::class));
|
||||
|
||||
return $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web client service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return WebClient
|
||||
*/
|
||||
public function getWebClientService(Container $container): WebClient
|
||||
{
|
||||
/** @var Input $input */
|
||||
$input = $container->get(Input::class);
|
||||
$userAgent = $input->server->getString('HTTP_USER_AGENT', '');
|
||||
$acceptEncoding = $input->server->getString('HTTP_ACCEPT_ENCODING', '');
|
||||
$acceptLanguage = $input->server->getString('HTTP_ACCEPT_LANGUAGE', '');
|
||||
|
||||
return new WebClient($userAgent, $acceptEncoding, $acceptLanguage);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\Service;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\FrameworkWebsite\Asset\MixPathPackage;
|
||||
use Joomla\FrameworkWebsite\Renderer\ApplicationContext;
|
||||
use Joomla\FrameworkWebsite\Renderer\FrameworkExtension;
|
||||
use Joomla\FrameworkWebsite\Renderer\FrameworkTwigRuntime;
|
||||
use Joomla\Preload\PreloadManager;
|
||||
use Joomla\Renderer\RendererInterface;
|
||||
use Joomla\Renderer\TwigRenderer;
|
||||
use Symfony\Component\Asset\Packages;
|
||||
use Symfony\Component\Asset\PathPackage;
|
||||
use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy;
|
||||
use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy;
|
||||
use Twig\Cache\CacheInterface;
|
||||
use Twig\Cache\FilesystemCache;
|
||||
use Twig\Cache\NullCache;
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\DebugExtension;
|
||||
use Twig\Extension\ProfilerExtension;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
use Twig\Loader\LoaderInterface;
|
||||
use Twig\Profiler\Profile;
|
||||
use Twig\RuntimeLoader\ContainerRuntimeLoader;
|
||||
|
||||
/**
|
||||
* Templating service provider
|
||||
*/
|
||||
class TemplatingProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
$container->alias(Packages::class, 'asset.packages')
|
||||
->share('asset.packages', [$this, 'getAssetPackagesService'], true);
|
||||
|
||||
$container->alias(RendererInterface::class, 'renderer')
|
||||
->alias(TwigRenderer::class, 'renderer')
|
||||
->share('renderer', [$this, 'getRendererService'], true);
|
||||
|
||||
$container->alias(CacheInterface::class, 'twig.cache')
|
||||
->alias(\Twig_CacheInterface::class, 'twig.cache')
|
||||
->share('twig.cache', [$this, 'getTwigCacheService'], true);
|
||||
|
||||
$container->alias(Environment::class, 'twig.environment')
|
||||
->alias(\Twig_Environment::class, 'twig.environment')
|
||||
->share('twig.environment', [$this, 'getTwigEnvironmentService'], true);
|
||||
|
||||
$container->alias(DebugExtension::class, 'twig.extension.debug')
|
||||
->alias(\Twig_Extension_Debug::class, 'twig.extension.debug')
|
||||
->share('twig.extension.debug', [$this, 'getTwigExtensionDebugService'], true);
|
||||
|
||||
$container->alias(FrameworkExtension::class, 'twig.extension.framework')
|
||||
->share('twig.extension.framework', [$this, 'getTwigExtensionFrameworkService'], true);
|
||||
|
||||
// This service cannot be protected as it is decorated when the debug bar is available
|
||||
$container->alias(ProfilerExtension::class, 'twig.extension.profiler')
|
||||
->alias(\Twig_Extension_Profiler::class, 'twig.extension.profiler')
|
||||
->share('twig.extension.profiler', [$this, 'getTwigExtensionProfilerService']);
|
||||
|
||||
$container->alias(LoaderInterface::class, 'twig.loader')
|
||||
->alias(\Twig_LoaderInterface::class, 'twig.loader')
|
||||
->share('twig.loader', [$this, 'getTwigLoaderService'], true);
|
||||
|
||||
$container->alias(Profile::class, 'twig.profiler.profile')
|
||||
->alias(\Twig_Profiler_Profile::class, 'twig.profiler.profile')
|
||||
->share('twig.profiler.profile', [$this, 'getTwigProfilerProfileService'], true);
|
||||
|
||||
$container->alias(FrameworkTwigRuntime::class, 'twig.runtime.framework')
|
||||
->share('twig.runtime.framework', [$this, 'getTwigRuntimeFrameworkService'], true);
|
||||
|
||||
$container->alias(ContainerRuntimeLoader::class, 'twig.runtime.loader')
|
||||
->alias(\Twig_ContainerRuntimeLoader::class, 'twig.runtime.loader')
|
||||
->share('twig.runtime.loader', [$this, 'getTwigRuntimeLoaderService'], true);
|
||||
|
||||
$this->tagTwigExtensions($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `asset.packages` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Packages
|
||||
*/
|
||||
public function getAssetPackagesService(Container $container): Packages
|
||||
{
|
||||
/** @var AbstractApplication $app */
|
||||
$app = $container->get(AbstractApplication::class);
|
||||
|
||||
$context = new ApplicationContext($app);
|
||||
|
||||
$mediaPath = $app->get('uri.media.path', '/media/');
|
||||
|
||||
$defaultPackage = new PathPackage($mediaPath, new EmptyVersionStrategy, $context);
|
||||
|
||||
$mixStrategy = new MixPathPackage(
|
||||
$defaultPackage,
|
||||
$mediaPath,
|
||||
new JsonManifestVersionStrategy(JPATH_ROOT . '/www/media/mix-manifest.json'),
|
||||
$context
|
||||
);
|
||||
|
||||
return new Packages(
|
||||
$defaultPackage,
|
||||
[
|
||||
'mix' => $mixStrategy,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `renderer` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return RendererInterface
|
||||
*/
|
||||
public function getRendererService(Container $container): RendererInterface
|
||||
{
|
||||
return new TwigRenderer($container->get('twig.environment'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.cache` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return \Twig_CacheInterface
|
||||
*/
|
||||
public function getTwigCacheService(Container $container): \Twig_CacheInterface
|
||||
{
|
||||
/** @var \Joomla\Registry\Registry $config */
|
||||
$config = $container->get('config');
|
||||
|
||||
// Pull down the renderer config
|
||||
$cacheEnabled = $config->get('template.cache.enabled', false);
|
||||
$cachePath = $config->get('template.cache.path', 'cache/twig');
|
||||
$debug = $config->get('template.debug', false);
|
||||
|
||||
if ($debug === false && $cacheEnabled !== false)
|
||||
{
|
||||
return new FilesystemCache(JPATH_ROOT . '/' . $cachePath);
|
||||
}
|
||||
|
||||
return new NullCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.environment` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Environment
|
||||
*/
|
||||
public function getTwigEnvironmentService(Container $container): Environment
|
||||
{
|
||||
/** @var \Joomla\Registry\Registry $config */
|
||||
$config = $container->get('config');
|
||||
|
||||
$debug = $config->get('template.debug', false);
|
||||
|
||||
$environment = new Environment(
|
||||
$container->get('twig.loader'),
|
||||
['debug' => $debug]
|
||||
);
|
||||
|
||||
// Add the runtime loader
|
||||
$environment->addRuntimeLoader($container->get('twig.runtime.loader'));
|
||||
|
||||
// Set up the environment's caching service
|
||||
$environment->setCache($container->get('twig.cache'));
|
||||
|
||||
// Add the Twig extensions
|
||||
$environment->setExtensions($container->getTagged('twig.extension'));
|
||||
|
||||
// Add a global tracking the debug states
|
||||
$environment->addGlobal('appDebug', $config->get('debug', false));
|
||||
$environment->addGlobal('fwDebug', $debug);
|
||||
|
||||
return $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.extension.debug` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return DebugExtension
|
||||
*/
|
||||
public function getTwigExtensionDebugService(Container $container): DebugExtension
|
||||
{
|
||||
return new DebugExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.extension.framework` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return FrameworkExtension
|
||||
*/
|
||||
public function getTwigExtensionFrameworkService(Container $container): FrameworkExtension
|
||||
{
|
||||
return new FrameworkExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.extension.profiler` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ProfilerExtension
|
||||
*/
|
||||
public function getTwigExtensionProfilerService(Container $container): ProfilerExtension
|
||||
{
|
||||
return new ProfilerExtension($container->get('twig.profiler.profile'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.loader` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return \Twig_LoaderInterface
|
||||
*/
|
||||
public function getTwigLoaderService(Container $container): \Twig_LoaderInterface
|
||||
{
|
||||
return new FilesystemLoader([JPATH_TEMPLATES]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.profiler.profile` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Profile
|
||||
*/
|
||||
public function getTwigProfilerProfileService(Container $container): Profile
|
||||
{
|
||||
return new Profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.runtime.framework` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return FrameworkTwigRuntime
|
||||
*/
|
||||
public function getTwigRuntimeFrameworkService(Container $container): FrameworkTwigRuntime
|
||||
{
|
||||
return new FrameworkTwigRuntime(
|
||||
$container->get(AbstractApplication::class),
|
||||
$container->get(PreloadManager::class),
|
||||
JPATH_ROOT . '/www/media/sri-manifest.json'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `twig.runtime.loader` service
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ContainerRuntimeLoader
|
||||
*/
|
||||
public function getTwigRuntimeLoaderService(Container $container): ContainerRuntimeLoader
|
||||
{
|
||||
return new ContainerRuntimeLoader($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag services which are Twig extensions
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function tagTwigExtensions(Container $container): void
|
||||
{
|
||||
/** @var \Joomla\Registry\Registry $config */
|
||||
$config = $container->get('config');
|
||||
|
||||
$debug = $config->get('template.debug', false);
|
||||
|
||||
$twigExtensions = ['twig.extension.framework'];
|
||||
|
||||
if ($debug)
|
||||
{
|
||||
$twigExtensions[] = 'twig.extension.debug';
|
||||
}
|
||||
|
||||
$container->tag('twig.extension', $twigExtensions);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\Service\Provider;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\User\UserFactory;
|
||||
use Joomla\CMS\User\UserFactoryInterface;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
|
||||
/**
|
||||
* Service provider for the user dependency
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class User implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->alias('user.factory', UserFactoryInterface::class)
|
||||
->alias(UserFactory::class, UserFactoryInterface::class)
|
||||
->share(
|
||||
UserFactoryInterface::class,
|
||||
function (Container $container)
|
||||
{
|
||||
return new UserFactory($container->get(DatabaseInterface::class));
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,336 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\Session;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\Application\AbstractApplication;
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Session\SessionInterface;
|
||||
|
||||
/**
|
||||
* Manager for optional session metadata.
|
||||
*
|
||||
* @since 3.8.6
|
||||
* @internal
|
||||
*/
|
||||
final class MetadataManager
|
||||
{
|
||||
/**
|
||||
* Internal variable indicating a session record exists.
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
* @note Once PHP 7.1 is the minimum supported version this should become a private constant
|
||||
*/
|
||||
private static $sessionRecordExists = 1;
|
||||
|
||||
/**
|
||||
* Internal variable indicating a session record does not exist.
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
* @note Once PHP 7.1 is the minimum supported version this should become a private constant
|
||||
*/
|
||||
private static $sessionRecordDoesNotExist = 0;
|
||||
|
||||
/**
|
||||
* Internal variable indicating an unknown session record statue.
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
* @note Once PHP 7.1 is the minimum supported version this should become a private constant
|
||||
*/
|
||||
private static $sessionRecordUnknown = -1;
|
||||
|
||||
/**
|
||||
* Application object.
|
||||
*
|
||||
* @var AbstractApplication
|
||||
* @since 3.8.6
|
||||
*/
|
||||
private $app;
|
||||
|
||||
/**
|
||||
* Database driver.
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
* @since 3.8.6
|
||||
*/
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* MetadataManager constructor.
|
||||
*
|
||||
* @param AbstractApplication $app Application object.
|
||||
* @param DatabaseInterface $db Database driver.
|
||||
*
|
||||
* @since 3.8.6
|
||||
*/
|
||||
public function __construct(AbstractApplication $app, DatabaseInterface $db)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the metadata record if it does not exist.
|
||||
*
|
||||
* @param SessionInterface $session The session to create the metadata record for.
|
||||
* @param User $user The user to associate with the record.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.8.6
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function createRecordIfNonExisting(SessionInterface $session, User $user)
|
||||
{
|
||||
$exists = $this->checkSessionRecordExists($session->getId());
|
||||
|
||||
// Only touch the database if the record does not already exist
|
||||
if ($exists !== self::$sessionRecordExists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->createSessionRecord($session, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the metadata record if it does not exist.
|
||||
*
|
||||
* @param SessionInterface $session The session to create or update the metadata record for.
|
||||
* @param User $user The user to associate with the record.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function createOrUpdateRecord(SessionInterface $session, User $user)
|
||||
{
|
||||
$exists = $this->checkSessionRecordExists($session->getId());
|
||||
|
||||
// Do not try to touch the database if we can't determine the record state
|
||||
if ($exists === self::$sessionRecordUnknown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ($exists === self::$sessionRecordDoesNotExist)
|
||||
{
|
||||
$this->createSessionRecord($session, $user);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->updateSessionRecord($session, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete records with a timestamp prior to the given time.
|
||||
*
|
||||
* @param integer $time The time records should be deleted if expired before.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.8.6
|
||||
*/
|
||||
public function deletePriorTo($time)
|
||||
{
|
||||
$query = $this->db->getQuery(true)
|
||||
->delete($this->db->quoteName('#__session'))
|
||||
->where($this->db->quoteName('time') . ' < :time')
|
||||
->bind(':time', $time, ParameterType::INTEGER);
|
||||
|
||||
$this->db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$this->db->execute();
|
||||
}
|
||||
catch (ExecutionFailureException $exception)
|
||||
{
|
||||
// Since garbage collection does not result in a fatal error when run in the session API, we don't allow it here either.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the session record exists
|
||||
*
|
||||
* @param string $sessionId The session ID to check
|
||||
*
|
||||
* @return integer Status value for record presence
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function checkSessionRecordExists(string $sessionId): int
|
||||
{
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('session_id'))
|
||||
->from($this->db->quoteName('#__session'))
|
||||
->where($this->db->quoteName('session_id') . ' = :session_id')
|
||||
->bind(':session_id', $sessionId)
|
||||
->setLimit(1);
|
||||
|
||||
$this->db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$exists = $this->db->loadResult();
|
||||
}
|
||||
catch (ExecutionFailureException $e)
|
||||
{
|
||||
return self::$sessionRecordUnknown;
|
||||
}
|
||||
|
||||
if ($exists)
|
||||
{
|
||||
return self::$sessionRecordExists;
|
||||
}
|
||||
|
||||
return self::$sessionRecordDoesNotExist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the session record
|
||||
*
|
||||
* @param SessionInterface $session The session to create the metadata record for.
|
||||
* @param User $user The user to associate with the record.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function createSessionRecord(SessionInterface $session, User $user)
|
||||
{
|
||||
$query = $this->db->getQuery(true);
|
||||
|
||||
$time = $session->isNew() ? time() : $session->get('session.timer.start');
|
||||
|
||||
$columns = [
|
||||
$this->db->quoteName('session_id'),
|
||||
$this->db->quoteName('guest'),
|
||||
$this->db->quoteName('time'),
|
||||
$this->db->quoteName('userid'),
|
||||
$this->db->quoteName('username'),
|
||||
];
|
||||
|
||||
// Add query placeholders
|
||||
$values = [
|
||||
':session_id',
|
||||
':guest',
|
||||
':time',
|
||||
':user_id',
|
||||
':username',
|
||||
];
|
||||
|
||||
// Bind query values
|
||||
$sessionId = $session->getId();
|
||||
$userIsGuest = $user->guest;
|
||||
$userId = $user->id;
|
||||
$username = $user->username === null ? '' : $user->username;
|
||||
|
||||
$query->bind(':session_id', $sessionId)
|
||||
->bind(':guest', $userIsGuest, ParameterType::INTEGER)
|
||||
->bind(':time', $time)
|
||||
->bind(':user_id', $userId, ParameterType::INTEGER)
|
||||
->bind(':username', $username);
|
||||
|
||||
if ($this->app instanceof CMSApplication && !$this->app->get('shared_session', false))
|
||||
{
|
||||
$clientId = $this->app->getClientId();
|
||||
|
||||
$columns[] = $this->db->quoteName('client_id');
|
||||
$values[] = ':client_id';
|
||||
|
||||
$query->bind(':client_id', $clientId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
$query->insert($this->db->quoteName('#__session'))
|
||||
->columns($columns)
|
||||
->values(implode(', ', $values));
|
||||
|
||||
$this->db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$this->db->execute();
|
||||
}
|
||||
catch (ExecutionFailureException $e)
|
||||
{
|
||||
// This failure isn't critical, we can go on without the metadata
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the session record
|
||||
*
|
||||
* @param SessionInterface $session The session to update the metadata record for.
|
||||
* @param User $user The user to associate with the record.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function updateSessionRecord(SessionInterface $session, User $user)
|
||||
{
|
||||
$query = $this->db->getQuery(true);
|
||||
|
||||
$time = time();
|
||||
|
||||
$setValues = [
|
||||
$this->db->quoteName('guest') . ' = :guest',
|
||||
$this->db->quoteName('time') . ' = :time',
|
||||
$this->db->quoteName('userid') . ' = :user_id',
|
||||
$this->db->quoteName('username') . ' = :username',
|
||||
];
|
||||
|
||||
// Bind query values
|
||||
$sessionId = $session->getId();
|
||||
$userIsGuest = $user->guest;
|
||||
$userId = $user->id;
|
||||
$username = $user->username === null ? '' : $user->username;
|
||||
|
||||
$query->bind(':session_id', $sessionId)
|
||||
->bind(':guest', $userIsGuest, ParameterType::INTEGER)
|
||||
->bind(':time', $time)
|
||||
->bind(':user_id', $userId, ParameterType::INTEGER)
|
||||
->bind(':username', $username);
|
||||
|
||||
if ($this->app instanceof CMSApplication && !$this->app->get('shared_session', false))
|
||||
{
|
||||
$clientId = $this->app->getClientId();
|
||||
|
||||
$setValues[] = $this->db->quoteName('client_id') . ' = :client_id';
|
||||
|
||||
$query->bind(':client_id', $clientId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
$query->update($this->db->quoteName('#__session'))
|
||||
->set($setValues)
|
||||
->where($this->db->quoteName('session_id') . ' = :session_id');
|
||||
|
||||
$this->db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$this->db->execute();
|
||||
}
|
||||
catch (ExecutionFailureException $e)
|
||||
{
|
||||
// This failure isn't critical, we can go on without the metadata
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\String;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Algo26\IdnaConvert\ToIdn;
|
||||
use Algo26\IdnaConvert\ToUnicode;
|
||||
use Joomla\Uri\UriHelper;
|
||||
|
||||
/**
|
||||
* Joomla Platform String Punycode Class
|
||||
*
|
||||
* Class for handling UTF-8 URLs
|
||||
* Wraps the Punycode library
|
||||
* All functions assume the validity of utf-8 URLs.
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
abstract class PunycodeHelper
|
||||
{
|
||||
/**
|
||||
* Transforms a UTF-8 string to a Punycode string
|
||||
*
|
||||
* @param string $utfString The UTF-8 string to transform
|
||||
*
|
||||
* @return string The punycode string
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static function toPunycode($utfString)
|
||||
{
|
||||
return (new ToIdn)->convert($utfString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Punycode string to a UTF-8 string
|
||||
*
|
||||
* @param string $punycodeString The Punycode string to transform
|
||||
*
|
||||
* @return string The UF-8 URL
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static function fromPunycode($punycodeString)
|
||||
{
|
||||
return (new ToUnicode)->convert($punycodeString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a UTF-8 URL to a Punycode URL
|
||||
*
|
||||
* @param string $uri The UTF-8 URL to transform
|
||||
*
|
||||
* @return string The punycode URL
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static function urlToPunycode($uri)
|
||||
{
|
||||
$parsed = UriHelper::parse_url($uri);
|
||||
|
||||
if (!isset($parsed['host']) || $parsed['host'] == '')
|
||||
{
|
||||
// If there is no host we do not need to convert it.
|
||||
return $uri;
|
||||
}
|
||||
|
||||
$host = $parsed['host'];
|
||||
$hostExploded = explode('.', $host);
|
||||
$newhost = '';
|
||||
|
||||
foreach ($hostExploded as $hostex)
|
||||
{
|
||||
$hostex = static::toPunycode($hostex);
|
||||
$newhost .= $hostex . '.';
|
||||
}
|
||||
|
||||
$newhost = substr($newhost, 0, -1);
|
||||
$newuri = '';
|
||||
|
||||
if (!empty($parsed['scheme']))
|
||||
{
|
||||
// Assume :// is required although it is not always.
|
||||
$newuri .= $parsed['scheme'] . '://';
|
||||
}
|
||||
|
||||
if (!empty($newhost))
|
||||
{
|
||||
$newuri .= $newhost;
|
||||
}
|
||||
|
||||
if (!empty($parsed['port']))
|
||||
{
|
||||
$newuri .= ':' . $parsed['port'];
|
||||
}
|
||||
|
||||
if (!empty($parsed['path']))
|
||||
{
|
||||
$newuri .= $parsed['path'];
|
||||
}
|
||||
|
||||
if (!empty($parsed['query']))
|
||||
{
|
||||
$newuri .= '?' . $parsed['query'];
|
||||
}
|
||||
|
||||
if (!empty($parsed['fragment']))
|
||||
{
|
||||
$newuri .= '#' . $parsed['fragment'];
|
||||
}
|
||||
|
||||
return $newuri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Punycode URL to a UTF-8 URL
|
||||
*
|
||||
* @param string $uri The Punycode URL to transform
|
||||
*
|
||||
* @return string The UTF-8 URL
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static function urlToUTF8($uri)
|
||||
{
|
||||
if (empty($uri))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$parsed = UriHelper::parse_url($uri);
|
||||
|
||||
if (!isset($parsed['host']) || $parsed['host'] == '')
|
||||
{
|
||||
// If there is no host we do not need to convert it.
|
||||
return $uri;
|
||||
}
|
||||
|
||||
$host = $parsed['host'];
|
||||
$hostExploded = explode('.', $host);
|
||||
$newhost = '';
|
||||
|
||||
foreach ($hostExploded as $hostex)
|
||||
{
|
||||
$hostex = self::fromPunycode($hostex);
|
||||
$newhost .= $hostex . '.';
|
||||
}
|
||||
|
||||
$newhost = substr($newhost, 0, -1);
|
||||
$newuri = '';
|
||||
|
||||
if (!empty($parsed['scheme']))
|
||||
{
|
||||
// Assume :// is required although it is not always.
|
||||
$newuri .= $parsed['scheme'] . '://';
|
||||
}
|
||||
|
||||
if (!empty($newhost))
|
||||
{
|
||||
$newuri .= $newhost;
|
||||
}
|
||||
|
||||
if (!empty($parsed['port']))
|
||||
{
|
||||
$newuri .= ':' . $parsed['port'];
|
||||
}
|
||||
|
||||
if (!empty($parsed['path']))
|
||||
{
|
||||
$newuri .= $parsed['path'];
|
||||
}
|
||||
|
||||
if (!empty($parsed['query']))
|
||||
{
|
||||
$newuri .= '?' . $parsed['query'];
|
||||
}
|
||||
|
||||
if (!empty($parsed['fragment']))
|
||||
{
|
||||
$newuri .= '#' . $parsed['fragment'];
|
||||
}
|
||||
|
||||
return $newuri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a UTF-8 email to a Punycode email
|
||||
* This assumes a valid email address
|
||||
*
|
||||
* @param string $email The UTF-8 email to transform
|
||||
*
|
||||
* @return string The punycode email
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static function emailToPunycode($email)
|
||||
{
|
||||
$explodedAddress = explode('@', $email);
|
||||
|
||||
// Not addressing UTF-8 user names
|
||||
$newEmail = $explodedAddress[0];
|
||||
|
||||
if (!empty($explodedAddress[1]))
|
||||
{
|
||||
$domainExploded = explode('.', $explodedAddress[1]);
|
||||
$newdomain = '';
|
||||
|
||||
foreach ($domainExploded as $domainex)
|
||||
{
|
||||
$domainex = static::toPunycode($domainex);
|
||||
$newdomain .= $domainex . '.';
|
||||
}
|
||||
|
||||
$newdomain = substr($newdomain, 0, -1);
|
||||
$newEmail = $newEmail . '@' . $newdomain;
|
||||
}
|
||||
|
||||
return $newEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Punycode email to a UTF-8 email
|
||||
* This assumes a valid email address
|
||||
*
|
||||
* @param string $email The punycode email to transform
|
||||
*
|
||||
* @return string The punycode email
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static function emailToUTF8($email)
|
||||
{
|
||||
$explodedAddress = explode('@', $email);
|
||||
|
||||
// Not addressing UTF-8 user names
|
||||
$newEmail = $explodedAddress[0];
|
||||
|
||||
if (!empty($explodedAddress[1]))
|
||||
{
|
||||
$domainExploded = explode('.', $explodedAddress[1]);
|
||||
$newdomain = '';
|
||||
|
||||
foreach ($domainExploded as $domainex)
|
||||
{
|
||||
$domainex = static::fromPunycode($domainex);
|
||||
$newdomain .= $domainex . '.';
|
||||
}
|
||||
|
||||
$newdomain = substr($newdomain, 0, -1);
|
||||
$newEmail = $newEmail . '@' . $newdomain;
|
||||
}
|
||||
|
||||
return $newEmail;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,934 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\User;
|
||||
|
||||
\defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\Access\Access;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
/**
|
||||
* User class. Handles all application interaction with a user
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
class User extends CMSObject
|
||||
{
|
||||
/**
|
||||
* A cached switch for if this user has root access rights.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $isRoot = null;
|
||||
|
||||
/**
|
||||
* Unique id
|
||||
*
|
||||
* @var integer
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $id = null;
|
||||
|
||||
/**
|
||||
* The user's real name (or nickname)
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $name = null;
|
||||
|
||||
/**
|
||||
* The login name
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $username = null;
|
||||
|
||||
/**
|
||||
* The email
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $email = null;
|
||||
|
||||
/**
|
||||
* MD5 encrypted password
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $password = null;
|
||||
|
||||
/**
|
||||
* Clear password, only available when a new password is set for a user
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $password_clear = '';
|
||||
|
||||
/**
|
||||
* Block status
|
||||
*
|
||||
* @var integer
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $block = null;
|
||||
|
||||
/**
|
||||
* Should this user receive system email
|
||||
*
|
||||
* @var integer
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $sendEmail = null;
|
||||
|
||||
/**
|
||||
* Date the user was registered
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $registerDate = null;
|
||||
|
||||
/**
|
||||
* Date of last visit
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $lastvisitDate = null;
|
||||
|
||||
/**
|
||||
* Activation hash
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $activation = null;
|
||||
|
||||
/**
|
||||
* User parameters
|
||||
*
|
||||
* @var Registry
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $params = null;
|
||||
|
||||
/**
|
||||
* Associative array of user names => group ids
|
||||
*
|
||||
* @var array
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $groups = array();
|
||||
|
||||
/**
|
||||
* Guest status
|
||||
*
|
||||
* @var integer
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public $guest = null;
|
||||
|
||||
/**
|
||||
* Last Reset Time
|
||||
*
|
||||
* @var string
|
||||
* @since 3.0.1
|
||||
*/
|
||||
public $lastResetTime = null;
|
||||
|
||||
/**
|
||||
* Count since last Reset Time
|
||||
*
|
||||
* @var integer
|
||||
* @since 3.0.1
|
||||
*/
|
||||
public $resetCount = null;
|
||||
|
||||
/**
|
||||
* Flag to require the user's password be reset
|
||||
*
|
||||
* @var integer
|
||||
* @since 3.2
|
||||
*/
|
||||
public $requireReset = null;
|
||||
|
||||
/**
|
||||
* User parameters
|
||||
*
|
||||
* @var Registry
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $_params = null;
|
||||
|
||||
/**
|
||||
* Authorised access groups
|
||||
*
|
||||
* @var array
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $_authGroups = null;
|
||||
|
||||
/**
|
||||
* Authorised access levels
|
||||
*
|
||||
* @var array
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $_authLevels = null;
|
||||
|
||||
/**
|
||||
* Authorised access actions
|
||||
*
|
||||
* @var array
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $_authActions = null;
|
||||
|
||||
/**
|
||||
* Error message
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $_errorMsg = null;
|
||||
|
||||
/**
|
||||
* @var array User instances container.
|
||||
* @since 1.7.3
|
||||
*/
|
||||
protected static $instances = array();
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the language
|
||||
*
|
||||
* @param integer $identifier The primary key of the user to load (optional).
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function __construct($identifier = 0)
|
||||
{
|
||||
// Create the user parameters object
|
||||
$this->_params = new Registry;
|
||||
|
||||
// Load the user if it exists
|
||||
if (!empty($identifier))
|
||||
{
|
||||
$this->load($identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialise
|
||||
$this->id = 0;
|
||||
$this->sendEmail = 0;
|
||||
$this->aid = 0;
|
||||
$this->guest = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the global User object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* @param integer $identifier The primary key of the user to load (optional).
|
||||
*
|
||||
* @return User The User object.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @deprecated 5.0 Load the user service from the dependency injection container or via $app->getIdentity()
|
||||
*/
|
||||
public static function getInstance($identifier = 0)
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'%1$s() is deprecated. Load the user from the dependency injection container or via %2$s::getApplication()->getIdentity().',
|
||||
__METHOD__,
|
||||
__CLASS__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
// Find the user id
|
||||
if (!is_numeric($identifier))
|
||||
{
|
||||
return Factory::getContainer()->get(UserFactoryInterface::class)->loadUserByUsername($identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
$id = $identifier;
|
||||
}
|
||||
|
||||
// If the $id is zero, just return an empty User.
|
||||
// Note: don't cache this user because it'll have a new ID on save!
|
||||
if ($id === 0)
|
||||
{
|
||||
return Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById($id);
|
||||
}
|
||||
|
||||
// Check if the user ID is already cached.
|
||||
if (empty(self::$instances[$id]))
|
||||
{
|
||||
self::$instances[$id] = Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById($id);
|
||||
}
|
||||
|
||||
return self::$instances[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a parameter value
|
||||
*
|
||||
* @param string $key Parameter key
|
||||
* @param mixed $default Parameter default value
|
||||
*
|
||||
* @return mixed The value or the default if it did not exist
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function getParam($key, $default = null)
|
||||
{
|
||||
return $this->_params->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set a parameter
|
||||
*
|
||||
* @param string $key Parameter key
|
||||
* @param mixed $value Parameter value
|
||||
*
|
||||
* @return mixed Set parameter value
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function setParam($key, $value)
|
||||
{
|
||||
return $this->_params->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set a default parameter if it does not exist
|
||||
*
|
||||
* @param string $key Parameter key
|
||||
* @param mixed $value Parameter value
|
||||
*
|
||||
* @return mixed Set parameter value
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function defParam($key, $value)
|
||||
{
|
||||
return $this->_params->def($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check User object authorisation against an access control
|
||||
* object and optionally an access extension object
|
||||
*
|
||||
* @param string $action The name of the action to check for permission.
|
||||
* @param string $assetname The name of the asset on which to perform the action.
|
||||
*
|
||||
* @return boolean True if authorised
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function authorise($action, $assetname = null)
|
||||
{
|
||||
// Make sure we only check for core.admin once during the run.
|
||||
if ($this->isRoot === null)
|
||||
{
|
||||
$this->isRoot = false;
|
||||
|
||||
// Check for the configuration file failsafe.
|
||||
$rootUser = Factory::getApplication()->get('root_user');
|
||||
|
||||
// The root_user variable can be a numeric user ID or a username.
|
||||
if (is_numeric($rootUser) && $this->id > 0 && $this->id == $rootUser)
|
||||
{
|
||||
$this->isRoot = true;
|
||||
}
|
||||
elseif ($this->username && $this->username == $rootUser)
|
||||
{
|
||||
$this->isRoot = true;
|
||||
}
|
||||
elseif ($this->id > 0)
|
||||
{
|
||||
// Get all groups against which the user is mapped.
|
||||
$identities = $this->getAuthorisedGroups();
|
||||
array_unshift($identities, $this->id * -1);
|
||||
|
||||
if (Access::getAssetRules(1)->allow('core.admin', $identities))
|
||||
{
|
||||
$this->isRoot = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->isRoot ? true : (bool) Access::check($this->id, $action, $assetname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return a list of all categories that a user has permission for a given action
|
||||
*
|
||||
* @param string $component The component from which to retrieve the categories
|
||||
* @param string $action The name of the section within the component from which to retrieve the actions.
|
||||
*
|
||||
* @return array List of categories that this group can do this action to (empty array if none). Categories must be published.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function getAuthorisedCategories($component, $action)
|
||||
{
|
||||
// Brute force method: get all published category rows for the component and check each one
|
||||
// @todo: Modify the way permissions are stored in the db to allow for faster implementation and better scaling
|
||||
$db = Factory::getDbo();
|
||||
|
||||
$subQuery = $db->getQuery(true)
|
||||
->select($db->quoteName(['id', 'asset_id']))
|
||||
->from($db->quoteName('#__categories'))
|
||||
->where(
|
||||
[
|
||||
$db->quoteName('extension') . ' = :component',
|
||||
$db->quoteName('published') . ' = 1',
|
||||
]
|
||||
);
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName(['c.id', 'a.name']))
|
||||
->from('(' . $subQuery . ') AS ' . $db->quoteName('c'))
|
||||
->join('INNER', $db->quoteName('#__assets', 'a'), $db->quoteName('c.asset_id') . ' = ' . $db->quoteName('a.id'))
|
||||
->bind(':component', $component);
|
||||
$db->setQuery($query);
|
||||
$allCategories = $db->loadObjectList('id');
|
||||
$allowedCategories = array();
|
||||
|
||||
foreach ($allCategories as $category)
|
||||
{
|
||||
if ($this->authorise($action, $category->name))
|
||||
{
|
||||
$allowedCategories[] = (int) $category->id;
|
||||
}
|
||||
}
|
||||
|
||||
return $allowedCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of the authorised access levels for the user
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function getAuthorisedViewLevels()
|
||||
{
|
||||
if ($this->_authLevels === null)
|
||||
{
|
||||
$this->_authLevels = array();
|
||||
}
|
||||
|
||||
if (empty($this->_authLevels))
|
||||
{
|
||||
$this->_authLevels = Access::getAuthorisedViewLevels($this->id);
|
||||
}
|
||||
|
||||
return $this->_authLevels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of the authorised user groups
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function getAuthorisedGroups()
|
||||
{
|
||||
if ($this->_authGroups === null)
|
||||
{
|
||||
$this->_authGroups = array();
|
||||
}
|
||||
|
||||
if (empty($this->_authGroups))
|
||||
{
|
||||
$this->_authGroups = Access::getGroupsByUser($this->id);
|
||||
}
|
||||
|
||||
return $this->_authGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the access rights cache of this user
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public function clearAccessRights()
|
||||
{
|
||||
$this->_authLevels = null;
|
||||
$this->_authGroups = null;
|
||||
$this->isRoot = null;
|
||||
Access::clearStatics();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass through method to the table for setting the last visit date
|
||||
*
|
||||
* @param integer $timestamp The timestamp, defaults to 'now'.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function setLastVisit($timestamp = null)
|
||||
{
|
||||
// Create the user table object
|
||||
/** @var \Joomla\CMS\Table\User $table */
|
||||
$table = $this->getTable();
|
||||
$table->load($this->id);
|
||||
|
||||
return $table->setLastVisit($timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the user timezone.
|
||||
*
|
||||
* If the user didn't set a timezone, it will return the server timezone
|
||||
*
|
||||
* @return \DateTimeZone
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public function getTimezone()
|
||||
{
|
||||
$timezone = $this->getParam('timezone', Factory::getApplication()->get('offset', 'GMT'));
|
||||
|
||||
return new \DateTimeZone($timezone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the user parameters
|
||||
*
|
||||
* @param object $params The user parameters object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function setParameters($params)
|
||||
{
|
||||
$this->_params = $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the user table object
|
||||
*
|
||||
* This function uses a static variable to store the table name of the user table to
|
||||
* instantiate. You can call this function statically to set the table name if
|
||||
* needed.
|
||||
*
|
||||
* @param string $type The user table name to be used
|
||||
* @param string $prefix The user table prefix to be used
|
||||
*
|
||||
* @return Table The user table object
|
||||
*
|
||||
* @note At 4.0 this method will no longer be static
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public static function getTable($type = null, $prefix = 'JTable')
|
||||
{
|
||||
static $tabletype;
|
||||
|
||||
// Set the default tabletype;
|
||||
if (!isset($tabletype))
|
||||
{
|
||||
$tabletype['name'] = 'user';
|
||||
$tabletype['prefix'] = 'JTable';
|
||||
}
|
||||
|
||||
// Set a custom table type is defined
|
||||
if (isset($type))
|
||||
{
|
||||
$tabletype['name'] = $type;
|
||||
$tabletype['prefix'] = $prefix;
|
||||
}
|
||||
|
||||
// Create the user table object
|
||||
return Table::getInstance($tabletype['name'], $tabletype['prefix']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to bind an associative array of data to a user object
|
||||
*
|
||||
* @param array &$array The associative array to bind to the object
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function bind(&$array)
|
||||
{
|
||||
// Let's check to see if the user is new or not
|
||||
if (empty($this->id))
|
||||
{
|
||||
// Check the password and create the crypted password
|
||||
if (empty($array['password']))
|
||||
{
|
||||
$array['password'] = UserHelper::genRandomPassword(32);
|
||||
$array['password2'] = $array['password'];
|
||||
}
|
||||
|
||||
// Not all controllers check the password, although they should.
|
||||
// Hence this code is required:
|
||||
if (isset($array['password2']) && $array['password'] != $array['password2'])
|
||||
{
|
||||
Factory::getApplication()->enqueueMessage(Text::_('JLIB_USER_ERROR_PASSWORD_NOT_MATCH'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->password_clear = ArrayHelper::getValue($array, 'password', '', 'string');
|
||||
|
||||
$array['password'] = UserHelper::hashPassword($array['password']);
|
||||
|
||||
// Set the registration timestamp
|
||||
$this->set('registerDate', Factory::getDate()->toSql());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Updating an existing user
|
||||
if (!empty($array['password']))
|
||||
{
|
||||
if ($array['password'] != $array['password2'])
|
||||
{
|
||||
$this->setError(Text::_('JLIB_USER_ERROR_PASSWORD_NOT_MATCH'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->password_clear = ArrayHelper::getValue($array, 'password', '', 'string');
|
||||
|
||||
// Check if the user is reusing the current password if required to reset their password
|
||||
if ($this->requireReset == 1 && UserHelper::verifyPassword($this->password_clear, $this->password))
|
||||
{
|
||||
$this->setError(Text::_('JLIB_USER_ERROR_CANNOT_REUSE_PASSWORD'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$array['password'] = UserHelper::hashPassword($array['password']);
|
||||
|
||||
// Reset the change password flag
|
||||
$array['requireReset'] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$array['password'] = $this->password;
|
||||
}
|
||||
|
||||
// Prevent updating internal fields
|
||||
unset($array['registerDate']);
|
||||
unset($array['lastvisitDate']);
|
||||
unset($array['lastResetTime']);
|
||||
unset($array['resetCount']);
|
||||
}
|
||||
|
||||
if (\array_key_exists('params', $array))
|
||||
{
|
||||
$this->_params->loadArray($array['params']);
|
||||
|
||||
if (\is_array($array['params']))
|
||||
{
|
||||
$params = (string) $this->_params;
|
||||
}
|
||||
else
|
||||
{
|
||||
$params = $array['params'];
|
||||
}
|
||||
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
// Bind the array
|
||||
if (!$this->setProperties($array))
|
||||
{
|
||||
$this->setError(Text::_('JLIB_USER_ERROR_BIND_ARRAY'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure its an integer
|
||||
$this->id = (int) $this->id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the User object to the database
|
||||
*
|
||||
* @param boolean $updateOnly Save the object only if not a new user
|
||||
* Currently only used in the user reset password method.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function save($updateOnly = false)
|
||||
{
|
||||
// Create the user table object
|
||||
$table = $this->getTable();
|
||||
$this->params = (string) $this->_params;
|
||||
$table->bind($this->getProperties());
|
||||
|
||||
// Allow an exception to be thrown.
|
||||
try
|
||||
{
|
||||
// Check and store the object.
|
||||
if (!$table->check())
|
||||
{
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If user is made a Super Admin group and user is NOT a Super Admin
|
||||
|
||||
// @todo ACL - this needs to be acl checked
|
||||
|
||||
$my = Factory::getUser();
|
||||
|
||||
// Are we creating a new user
|
||||
$isNew = empty($this->id);
|
||||
|
||||
// If we aren't allowed to create new users return
|
||||
if ($isNew && $updateOnly)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the old user
|
||||
$oldUser = new User($this->id);
|
||||
|
||||
// Access Checks
|
||||
|
||||
// The only mandatory check is that only Super Admins can operate on other Super Admin accounts.
|
||||
// To add additional business rules, use a user plugin and throw an Exception with onUserBeforeSave.
|
||||
|
||||
// Check if I am a Super Admin
|
||||
$iAmSuperAdmin = $my->authorise('core.admin');
|
||||
|
||||
$iAmRehashingSuperadmin = false;
|
||||
|
||||
if (($my->id == 0 && !$isNew) && $this->id == $oldUser->id && $oldUser->authorise('core.admin') && $oldUser->password != $this->password)
|
||||
{
|
||||
$iAmRehashingSuperadmin = true;
|
||||
}
|
||||
|
||||
// Check if we are using a CLI application
|
||||
$isCli = false;
|
||||
|
||||
if (Factory::getApplication()->isCli())
|
||||
{
|
||||
$isCli = true;
|
||||
}
|
||||
|
||||
// We are only worried about edits to this account if I am not a Super Admin.
|
||||
if ($iAmSuperAdmin != true && $iAmRehashingSuperadmin != true && $isCli != true)
|
||||
{
|
||||
// I am not a Super Admin, and this one is, so fail.
|
||||
if (!$isNew && Access::check($this->id, 'core.admin'))
|
||||
{
|
||||
throw new \RuntimeException('User not Super Administrator');
|
||||
}
|
||||
|
||||
if ($this->groups != null)
|
||||
{
|
||||
// I am not a Super Admin and I'm trying to make one.
|
||||
foreach ($this->groups as $groupId)
|
||||
{
|
||||
if (Access::checkGroup($groupId, 'core.admin'))
|
||||
{
|
||||
throw new \RuntimeException('User not Super Administrator');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fire the onUserBeforeSave event.
|
||||
PluginHelper::importPlugin('user');
|
||||
|
||||
$result = Factory::getApplication()->triggerEvent('onUserBeforeSave', array($oldUser->getProperties(), $isNew, $this->getProperties()));
|
||||
|
||||
if (\in_array(false, $result, true))
|
||||
{
|
||||
// Plugin will have to raise its own error or throw an exception.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the user data in the database
|
||||
$result = $table->store();
|
||||
|
||||
// Set the id for the User object in case we created a new user.
|
||||
if (empty($this->id))
|
||||
{
|
||||
$this->id = $table->get('id');
|
||||
}
|
||||
|
||||
if ($my->id == $table->id)
|
||||
{
|
||||
$registry = new Registry($table->params);
|
||||
$my->setParameters($registry);
|
||||
}
|
||||
|
||||
// Fire the onUserAfterSave event
|
||||
Factory::getApplication()->triggerEvent('onUserAfterSave', array($this->getProperties(), $isNew, $result, $this->getError()));
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to delete the User object from the database
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
PluginHelper::importPlugin('user');
|
||||
|
||||
// Trigger the onUserBeforeDelete event
|
||||
Factory::getApplication()->triggerEvent('onUserBeforeDelete', array($this->getProperties()));
|
||||
|
||||
// Create the user table object
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$result = $table->delete($this->id))
|
||||
{
|
||||
$this->setError($table->getError());
|
||||
}
|
||||
|
||||
// Trigger the onUserAfterDelete event
|
||||
Factory::getApplication()->triggerEvent('onUserAfterDelete', array($this->getProperties(), $result, $this->getError()));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to load a User object by user id number
|
||||
*
|
||||
* @param mixed $id The user id of the user to load
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function load($id)
|
||||
{
|
||||
// Create the user table object
|
||||
$table = $this->getTable();
|
||||
|
||||
// Load the UserModel object based on the user id or throw a warning.
|
||||
if (!$table->load($id))
|
||||
{
|
||||
// Reset to guest user
|
||||
$this->guest = 1;
|
||||
|
||||
Log::add(Text::sprintf('JLIB_USER_ERROR_UNABLE_TO_LOAD_USER', $id), Log::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the user parameters using the default XML file. We might want to
|
||||
* extend this in the future to allow for the ability to have custom
|
||||
* user parameters, but for right now we'll leave it how it is.
|
||||
*/
|
||||
|
||||
if ($table->params)
|
||||
{
|
||||
$this->_params->loadString($table->params);
|
||||
}
|
||||
|
||||
// Assuming all is well at this point let's bind the data
|
||||
$this->setProperties($table->getProperties());
|
||||
|
||||
// The user is no longer a guest
|
||||
if ($this->id != 0)
|
||||
{
|
||||
$this->guest = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->guest = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to allow serialize the object with minimal properties.
|
||||
*
|
||||
* @return array The names of the properties to include in serialization.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return array('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to recover the full object on unserialize.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
// Initialise some variables
|
||||
$this->_params = new Registry;
|
||||
|
||||
// Load the user if it exists
|
||||
if (!empty($this->id) && $this->load($this->id))
|
||||
{
|
||||
// Push user into cached instances.
|
||||
self::$instances[$this->id] = $this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialise
|
||||
$this->id = 0;
|
||||
$this->sendEmail = 0;
|
||||
$this->aid = 0;
|
||||
$this->guest = 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\User;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
|
||||
/**
|
||||
* Default factory for creating User objects
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class UserFactory implements UserFactoryInterface
|
||||
{
|
||||
/**
|
||||
* The database.
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
*/
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* UserFactory constructor.
|
||||
*
|
||||
* @param DatabaseInterface $db The database
|
||||
*/
|
||||
public function __construct(DatabaseInterface $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an instance of a user for the given id.
|
||||
*
|
||||
* @param int $id The id
|
||||
*
|
||||
* @return User
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function loadUserById(int $id): User
|
||||
{
|
||||
return new User($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an instance of a user for the given username.
|
||||
*
|
||||
* @param string $username The username
|
||||
*
|
||||
* @return User
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function loadUserByUsername(string $username): User
|
||||
{
|
||||
// Initialise some variables
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('id'))
|
||||
->from($this->db->quoteName('#__users'))
|
||||
->where($this->db->quoteName('username') . ' = :username')
|
||||
->bind(':username', $username)
|
||||
->setLimit(1);
|
||||
$this->db->setQuery($query);
|
||||
|
||||
return $this->loadUserById((int) $this->db->loadResult());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\CMS\User;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Interface defining a factory which can create User objects
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
interface UserFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Method to get an instance of a user for the given id.
|
||||
*
|
||||
* @param int $id The id
|
||||
*
|
||||
* @return User
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function loadUserById(int $id): User;
|
||||
|
||||
/**
|
||||
* Method to get an instance of a user for the given username.
|
||||
*
|
||||
* @param string $username The username
|
||||
*
|
||||
* @return User
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function loadUserByUsername(string $username): User;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\View\Package;
|
||||
|
||||
use Joomla\FrameworkWebsite\Helper;
|
||||
use Joomla\FrameworkWebsite\Model\PackageModel;
|
||||
use Joomla\FrameworkWebsite\Model\ReleaseModel;
|
||||
use Joomla\Renderer\RendererInterface;
|
||||
use Joomla\View\HtmlView;
|
||||
|
||||
/**
|
||||
* Package HTML view class for the application
|
||||
*/
|
||||
class PackageHtmlView extends HtmlView
|
||||
{
|
||||
/**
|
||||
* Helper object
|
||||
*
|
||||
* @var Helper
|
||||
*/
|
||||
private $helper;
|
||||
|
||||
/**
|
||||
* The active package
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $package = '';
|
||||
|
||||
/**
|
||||
* The package model object.
|
||||
*
|
||||
* @var PackageModel
|
||||
*/
|
||||
private $packageModel;
|
||||
|
||||
/**
|
||||
* The release model object.
|
||||
*
|
||||
* @var ReleaseModel
|
||||
*/
|
||||
private $releaseModel;
|
||||
|
||||
/**
|
||||
* Instantiate the view.
|
||||
*
|
||||
* @param PackageModel $packageModel The package model object.
|
||||
* @param ReleaseModel $releaseModel The release model object.
|
||||
* @param Helper $helper Helper object.
|
||||
* @param RendererInterface $renderer The renderer object.
|
||||
*/
|
||||
public function __construct(PackageModel $packageModel, ReleaseModel $releaseModel, Helper $helper, RendererInterface $renderer)
|
||||
{
|
||||
parent::__construct($renderer);
|
||||
|
||||
$this->helper = $helper;
|
||||
$this->packageModel = $packageModel;
|
||||
$this->releaseModel = $releaseModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to render the view
|
||||
*
|
||||
* @return string The rendered view
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$package = $this->packageModel->getPackage($this->package);
|
||||
|
||||
$this->setData(
|
||||
[
|
||||
'releases' => $this->releaseModel->getPackageHistory($package),
|
||||
'package' => $package,
|
||||
]
|
||||
);
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active package
|
||||
*
|
||||
* @param string $package The active package name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPackage(string $package): void
|
||||
{
|
||||
$this->package = $package;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* Joomla! Framework Website
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
|
||||
*/
|
||||
|
||||
namespace Joomla\FrameworkWebsite\View\Package;
|
||||
|
||||
use Joomla\FrameworkWebsite\Helper;
|
||||
use Joomla\FrameworkWebsite\Model\PackageModel;
|
||||
use Joomla\FrameworkWebsite\Model\ReleaseModel;
|
||||
use Joomla\Renderer\RendererInterface;
|
||||
use Joomla\View\HtmlView;
|
||||
|
||||
/**
|
||||
* Package HTML view class for the application
|
||||
*/
|
||||
class PackageHtmlView extends HtmlView
|
||||
{
|
||||
/**
|
||||
* Helper object
|
||||
*
|
||||
* @var Helper
|
||||
*/
|
||||
private $helper;
|
||||
|
||||
/**
|
||||
* The active package
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $package = '';
|
||||
|
||||
/**
|
||||
* The package model object.
|
||||
*
|
||||
* @var PackageModel
|
||||
*/
|
||||
private $packageModel;
|
||||
|
||||
/**
|
||||
* The release model object.
|
||||
*
|
||||
* @var ReleaseModel
|
||||
*/
|
||||
private $releaseModel;
|
||||
|
||||
/**
|
||||
* Instantiate the view.
|
||||
*
|
||||
* @param PackageModel $packageModel The package model object.
|
||||
* @param ReleaseModel $releaseModel The release model object.
|
||||
* @param Helper $helper Helper object.
|
||||
* @param RendererInterface $renderer The renderer object.
|
||||
*/
|
||||
public function __construct(PackageModel $packageModel, ReleaseModel $releaseModel, Helper $helper, RendererInterface $renderer)
|
||||
{
|
||||
parent::__construct($renderer);
|
||||
|
||||
$this->helper = $helper;
|
||||
$this->packageModel = $packageModel;
|
||||
$this->releaseModel = $releaseModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to render the view
|
||||
*
|
||||
* @return string The rendered view
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$package = $this->packageModel->getPackage($this->package);
|
||||
|
||||
$this->setData(
|
||||
[
|
||||
'releases' => $this->releaseModel->getPackageHistory($package),
|
||||
'package' => $package,
|
||||
]
|
||||
);
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active package
|
||||
*
|
||||
* @param string $package The active package name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPackage(string $package): void
|
||||
{
|
||||
$this->package = $package;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<system.web>
|
||||
<authorization>
|
||||
<deny users="*" />
|
||||
</authorization>
|
||||
</system.web>
|
||||
</configuration>
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><title></title>
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><title></title>
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><title></title>
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1,28 @@
|
|||
# If the Joomla site is installed within a folder
|
||||
# eg www.example.com/joomla/ then the robots.txt file
|
||||
# MUST be moved to the site root
|
||||
# eg www.example.com/robots.txt
|
||||
# AND the joomla folder name MUST be prefixed to all of the
|
||||
# paths.
|
||||
# eg the Disallow rule for the /administrator/ folder MUST
|
||||
# be changed to read
|
||||
# Disallow: /joomla/administrator/
|
||||
#
|
||||
# For more information about the robots.txt standard, see:
|
||||
# https://www.robotstxt.org/orig.html
|
||||
|
||||
User-agent: *
|
||||
Disallow: /administrator/
|
||||
Disallow: /bin/
|
||||
Disallow: /cache/
|
||||
Disallow: /cli/
|
||||
Disallow: /components/
|
||||
Disallow: /includes/
|
||||
Disallow: /installation/
|
||||
Disallow: /language/
|
||||
Disallow: /layouts/
|
||||
Disallow: /libraries/
|
||||
Disallow: /logs/
|
||||
Disallow: /modules/
|
||||
Disallow: /plugins/
|
||||
Disallow: /tmp/
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><title></title>
|
|
@ -0,0 +1,141 @@
|
|||
--
|
||||
-- DATABASE STRUCTURE FOR GENERIC CMS (Adapted from Joomla!)
|
||||
-- -- subject to change --
|
||||
--
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
--
|
||||
-- Table structure for table `llewellyn_menu`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `llewellyn_menu` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL COMMENT 'The display title of the menu item.',
|
||||
`alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'The SEF alias of the menu item.',
|
||||
`path` varchar(1024) NOT NULL COMMENT 'The computed path of the menu item based on the alias field.',
|
||||
`published` tinyint NOT NULL DEFAULT 0 COMMENT 'The published state of the menu link.',
|
||||
`parent_id` int unsigned NOT NULL DEFAULT 1 COMMENT 'The parent menu item in the menu tree.',
|
||||
`level` int unsigned NOT NULL DEFAULT 0 COMMENT 'The relative level in the tree.',
|
||||
`item_id` int unsigned NOT NULL DEFAULT 0 COMMENT 'FK to llewellyn_item.id',
|
||||
`checked_out` int unsigned COMMENT 'FK to llewellyn_users.id',
|
||||
`checked_out_time` datetime COMMENT 'The time the menu item was checked out.',
|
||||
`params` text NOT NULL COMMENT 'JSON encoded data for the menu item.',
|
||||
`lft` int NOT NULL DEFAULT 0 COMMENT 'Nested set lft.',
|
||||
`rgt` int NOT NULL DEFAULT 0 COMMENT 'Nested set rgt.',
|
||||
`home` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Indicates if this menu item is the home or default page.',
|
||||
`publish_up` datetime,
|
||||
`publish_down` datetime,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_item` (`item_id`),
|
||||
KEY `idx_left_right` (`lft`,`rgt`),
|
||||
KEY `idx_alias` (`alias`(100)),
|
||||
KEY `idx_path` (`path`(100))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=102;
|
||||
|
||||
--
|
||||
-- Table structure for table `llewellyn_session`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `llewellyn_session` (
|
||||
`session_id` varbinary(192) NOT NULL,
|
||||
`guest` tinyint unsigned DEFAULT 1,
|
||||
`time` int NOT NULL DEFAULT 0,
|
||||
`data` mediumtext,
|
||||
`userid` int DEFAULT 0,
|
||||
`username` varchar(150) DEFAULT '',
|
||||
PRIMARY KEY (`session_id`),
|
||||
KEY `userid` (`userid`),
|
||||
KEY `time` (`time`),
|
||||
KEY `guest` (`guest`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `llewellyn_users`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `llewellyn_users` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(400) NOT NULL DEFAULT '',
|
||||
`username` varchar(150) NOT NULL DEFAULT '',
|
||||
`email` varchar(100) NOT NULL DEFAULT '',
|
||||
`password` varchar(100) NOT NULL DEFAULT '',
|
||||
`block` tinyint NOT NULL DEFAULT 0,
|
||||
`sendEmail` tinyint DEFAULT 0,
|
||||
`registerDate` datetime NOT NULL,
|
||||
`lastvisitDate` datetime,
|
||||
`activation` varchar(100) NOT NULL DEFAULT '',
|
||||
`params` text NOT NULL,
|
||||
`lastResetTime` datetime COMMENT 'Date of last password reset',
|
||||
`resetCount` int NOT NULL DEFAULT 0 COMMENT 'Count of password resets since lastResetTime',
|
||||
`requireReset` tinyint NOT NULL DEFAULT 0 COMMENT 'Require user to reset password on next login',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_name` (`name`(100)),
|
||||
KEY `idx_block` (`block`),
|
||||
UNIQUE KEY `idx_username` (`username`),
|
||||
KEY `email` (`email`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `llewellyn_usergroups`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `llewellyn_usergroups` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
|
||||
`parent_id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Adjacency List Reference Id',
|
||||
`lft` int NOT NULL DEFAULT 0 COMMENT 'Nested set lft.',
|
||||
`rgt` int NOT NULL DEFAULT 0 COMMENT 'Nested set rgt.',
|
||||
`title` varchar(100) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_usergroup_parent_title_lookup` (`parent_id`,`title`),
|
||||
KEY `idx_usergroup_title_lookup` (`title`),
|
||||
KEY `idx_usergroup_adjacency_lookup` (`parent_id`),
|
||||
KEY `idx_usergroup_nested_set_lookup` (`lft`,`rgt`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `llewellyn_user_usergroup_map`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `llewellyn_user_usergroup_map` (
|
||||
`user_id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Foreign Key to llewellyn_users.id',
|
||||
`group_id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Foreign Key to llewellyn_usergroups.id',
|
||||
PRIMARY KEY (`user_id`,`group_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `llewellyn_item`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `llewellyn_item` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
|
||||
`introtext` mediumtext NOT NULL,
|
||||
`fulltext` mediumtext NOT NULL,
|
||||
`state` tinyint NOT NULL DEFAULT 0,
|
||||
`created` datetime NOT NULL,
|
||||
`created_by` int unsigned NOT NULL DEFAULT 0,
|
||||
`created_by_alias` varchar(255) NOT NULL DEFAULT '',
|
||||
`modified` datetime NOT NULL,
|
||||
`modified_by` int unsigned NOT NULL DEFAULT 0,
|
||||
`checked_out` int unsigned,
|
||||
`checked_out_time` datetime NULL DEFAULT NULL,
|
||||
`publish_up` datetime NULL DEFAULT NULL,
|
||||
`publish_down` datetime NULL DEFAULT NULL,
|
||||
`version` int unsigned NOT NULL DEFAULT 1,
|
||||
`ordering` int NOT NULL DEFAULT 0,
|
||||
`metakey` text,
|
||||
`metadesc` text NOT NULL,
|
||||
`hits` int unsigned NOT NULL DEFAULT 0,
|
||||
`metadata` text NOT NULL,
|
||||
`featured` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Set if article is featured.',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_checkout` (`checked_out`),
|
||||
KEY `idx_state` (`state`),
|
||||
KEY `idx_createdby` (`created_by`),
|
||||
KEY `idx_alias` (`alias`(191))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<location path=".">
|
||||
<system.webServer>
|
||||
<directoryBrowse enabled="false" />
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Joomla! Rule 1" stopProcessing="true">
|
||||
<match url="^(.*)$" ignoreCase="false" />
|
||||
<conditions logicalGrouping="MatchAny">
|
||||
<add input="{QUERY_STRING}" pattern="base64_encode[^(]*\([^)]*\)" ignoreCase="false" />
|
||||
<add input="{QUERY_STRING}" pattern="(>|%3C)([^s]*s)+cript.*(<|%3E)" />
|
||||
<add input="{QUERY_STRING}" pattern="GLOBALS(=|\[|\%[0-9A-Z]{0,2})" ignoreCase="false" />
|
||||
<add input="{QUERY_STRING}" pattern="_REQUEST(=|\[|\%[0-9A-Z]{0,2})" ignoreCase="false" />
|
||||
</conditions>
|
||||
<action type="CustomResponse" url="index.php" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
|
||||
</rule>
|
||||
<rule name="Joomla! Rule 2">
|
||||
<match url="(.*)" ignoreCase="false" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{URL}" pattern="^/index.php" ignoreCase="true" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="index.php" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
<httpProtocol>
|
||||
<customHeaders>
|
||||
<add name="X-Content-Type-Options" value="nosniff" />
|
||||
</customHeaders>
|
||||
</httpProtocol>
|
||||
</system.webServer>
|
||||
</location>
|
||||
</configuration>
|
Loading…
Reference in New Issue