mirror of
https://github.com/bckelley/SimpleMVC.git
synced 2026-08-24 03:34:11 -05:00
init commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
.git
|
||||||
|
.vscode
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule ^$ public/ [L]
|
||||||
|
RewriteRule (.*) public/$1 [L]
|
||||||
|
</IfModule>
|
||||||
@@ -0,0 +1,447 @@
|
|||||||
|
Attribution-NonCommercial-ShareAlike 4.0 International
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
|
does not provide legal services or legal advice. Distribution of
|
||||||
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
|
other relationship. Creative Commons makes its licenses and related
|
||||||
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
|
warranties regarding its licenses, any material licensed under their
|
||||||
|
terms and conditions, or any related information. Creative Commons
|
||||||
|
disclaims all liability for damages resulting from their use to the
|
||||||
|
fullest extent possible.
|
||||||
|
|
||||||
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
|
Creative Commons public licenses provide a standard set of terms and
|
||||||
|
conditions that creators and other rights holders may use to share
|
||||||
|
original works of authorship and other material subject to copyright
|
||||||
|
and certain other rights specified in the public license below. The
|
||||||
|
following considerations are for informational purposes only, are not
|
||||||
|
exhaustive, and do not form part of our licenses.
|
||||||
|
|
||||||
|
Considerations for licensors: Our public licenses are
|
||||||
|
intended for use by those authorized to give the public
|
||||||
|
permission to use material in ways otherwise restricted by
|
||||||
|
copyright and certain other rights. Our licenses are
|
||||||
|
irrevocable. Licensors should read and understand the terms
|
||||||
|
and conditions of the license they choose before applying it.
|
||||||
|
Licensors should also secure all rights necessary before
|
||||||
|
applying our licenses so that the public can reuse the
|
||||||
|
material as expected. Licensors should clearly mark any
|
||||||
|
material not subject to the license. This includes other CC-
|
||||||
|
licensed material, or material used under an exception or
|
||||||
|
limitation to copyright. More considerations for licensors:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
|
Considerations for the public: By using one of our public
|
||||||
|
licenses, a licensor grants the public permission to use the
|
||||||
|
licensed material under specified terms and conditions. If
|
||||||
|
the licensor's permission is not necessary for any reason--for
|
||||||
|
example, because of any applicable exception or limitation to
|
||||||
|
copyright--then that use is not regulated by the license. Our
|
||||||
|
licenses grant only permissions under copyright and certain
|
||||||
|
other rights that a licensor has authority to grant. Use of
|
||||||
|
the licensed material may still be restricted for other
|
||||||
|
reasons, including because others have copyright or other
|
||||||
|
rights in the material. A licensor may make special requests,
|
||||||
|
such as asking that all changes be marked or described.
|
||||||
|
Although not required by our licenses, you are encouraged to
|
||||||
|
respect those requests where reasonable. More considerations
|
||||||
|
for the public:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensees
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
||||||
|
Public License
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-NonCommercial-ShareAlike 4.0 International Public License
|
||||||
|
("Public License"). To the extent this Public License may be
|
||||||
|
interpreted as a contract, You are granted the Licensed Rights in
|
||||||
|
consideration of Your acceptance of these terms and conditions, and the
|
||||||
|
Licensor grants You such rights in consideration of benefits the
|
||||||
|
Licensor receives from making the Licensed Material available under
|
||||||
|
these terms and conditions.
|
||||||
|
|
||||||
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright
|
||||||
|
and Similar Rights in Your contributions to Adapted Material in
|
||||||
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
c. BY-NC-SA Compatible License means a license listed at
|
||||||
|
creativecommons.org/compatiblelicenses, approved by Creative
|
||||||
|
Commons as essentially the equivalent of this Public License.
|
||||||
|
|
||||||
|
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation,
|
||||||
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
|
Rights, without regard to how the rights are labeled or
|
||||||
|
categorized. For purposes of this Public License, the rights
|
||||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
e. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
|
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
g. License Elements means the license attributes listed in the name
|
||||||
|
of a Creative Commons Public License. The License Elements of this
|
||||||
|
Public License are Attribution, NonCommercial, and ShareAlike.
|
||||||
|
|
||||||
|
h. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
i. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
|
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
k. NonCommercial means not primarily intended for or directed towards
|
||||||
|
commercial advantage or monetary compensation. For purposes of
|
||||||
|
this Public License, the exchange of the Licensed Material for
|
||||||
|
other material subject to Copyright and Similar Rights by digital
|
||||||
|
file-sharing or similar means is NonCommercial provided there is
|
||||||
|
no payment of monetary compensation in connection with the
|
||||||
|
exchange.
|
||||||
|
|
||||||
|
l. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
m. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
n. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part, for NonCommercial purposes only by individuals,
|
||||||
|
non-profit organizations, and small businesses
|
||||||
|
(not qualifying as major corporations); and
|
||||||
|
|
||||||
|
b. produce, reproduce, and Share Adapted Material for
|
||||||
|
NonCommercial purposes only by individuals, non-profit
|
||||||
|
organizations, and small businesses
|
||||||
|
(not qualifying as major corporations).
|
||||||
|
|
||||||
|
5. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
|
License does not apply, and You do not need to comply with
|
||||||
|
its terms and conditions.
|
||||||
|
|
||||||
|
6. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
|
7. Media and formats; technical modifications allowed. The
|
||||||
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
|
8. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
|
recipient of the Licensed Material automatically
|
||||||
|
receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. Additional offer from the Licensor -- Adapted Material.
|
||||||
|
Every recipient of Adapted Material from You
|
||||||
|
automatically receives an offer from the Licensor to
|
||||||
|
exercise the Licensed Rights in the Adapted Material
|
||||||
|
under the conditions of the Adapter's License You apply.
|
||||||
|
|
||||||
|
c. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
9. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Restrictions on Major Corporations.
|
||||||
|
|
||||||
|
1. The use of the Licensed Material by major corporations is
|
||||||
|
strictly prohibited under this license. Major corporations
|
||||||
|
are defined as entities with a significant market presence,
|
||||||
|
substantial financial resources, and a broad customer base.
|
||||||
|
|
||||||
|
c. Share Back Requirement.
|
||||||
|
|
||||||
|
1. All users are required to share any Adapted Material back
|
||||||
|
to the original source, prominently mentioning the original
|
||||||
|
creator and providing a URI or hyperlink to the original
|
||||||
|
Licensed Material to the extent reasonably practicable.
|
||||||
|
|
||||||
|
d. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties, including when
|
||||||
|
the Licensed Material is used other than for NonCommercial
|
||||||
|
purposes.
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified
|
||||||
|
form), You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
b. ShareAlike.
|
||||||
|
|
||||||
|
In addition to the conditions in Section 3(a), if You Share
|
||||||
|
Adapted Material You produce, the following conditions also apply.
|
||||||
|
|
||||||
|
1. The Adapter's License You apply must be a Creative Commons
|
||||||
|
license with the same License Elements, this version or
|
||||||
|
later, or a BY-NC-SA Compatible License.
|
||||||
|
|
||||||
|
2. You must include the text of, or the URI or hyperlink to, the
|
||||||
|
Adapter's License You apply. You may satisfy this condition
|
||||||
|
in any reasonable manner based on the medium, means, and
|
||||||
|
context in which You Share Adapted Material.
|
||||||
|
|
||||||
|
3. You may not offer or impose any additional or different terms
|
||||||
|
or conditions on, or apply any Effective Technological
|
||||||
|
Measures to, Adapted Material that restrict exercise of the
|
||||||
|
rights granted under the Adapter's License You apply.
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database for NonCommercial purposes
|
||||||
|
only;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material,
|
||||||
|
including for purposes of Section 3(b); and
|
||||||
|
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons is not a party to its public
|
||||||
|
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||||
|
its public licenses to material it publishes and in those instances
|
||||||
|
will be considered the “Licensor.” The text of the Creative Commons
|
||||||
|
public licenses is dedicated to the public domain under the CC0 Public
|
||||||
|
Domain Dedication. Except for the limited purpose of indicating that
|
||||||
|
material is shared under a Creative Commons public license or as
|
||||||
|
otherwise permitted by the Creative Commons policies published at
|
||||||
|
creativecommons.org/policies, Creative Commons does not authorize the
|
||||||
|
use of the trademark "Creative Commons" or any other trademark or logo
|
||||||
|
of Creative Commons without its prior written consent including,
|
||||||
|
without limitation, in connection with any unauthorized modifications
|
||||||
|
to any of its public licenses or any other arrangements,
|
||||||
|
understandings, or agreements concerning use of licensed material. For
|
||||||
|
the avoidance of doubt, this paragraph does not form part of the
|
||||||
|
public licenses.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at creativecommons.org.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Options -Indexes
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?PHP
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Explanation:
|
||||||
|
* - The code loads the configuration file, which typically contains constants and settings.
|
||||||
|
* - It includes helper files for URL and session-related functions.
|
||||||
|
* - The spl_autoload_register function is used to automatically load class files when needed.
|
||||||
|
* - The anonymous function within spl_autoload_register dynamically requires the class file based on its name.
|
||||||
|
* - This allows for a more organized and modular structure in loading core libraries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Load Config
|
||||||
|
require_once 'config/config.php';
|
||||||
|
|
||||||
|
// Include URL Helper Functions
|
||||||
|
require_once 'helpers/url.php';
|
||||||
|
|
||||||
|
// Include Session Helper Functions
|
||||||
|
require_once 'helpers/sessions.php';
|
||||||
|
|
||||||
|
// Autoload Core Libraries using spl_autoload_register
|
||||||
|
spl_autoload_register(function ($className) {
|
||||||
|
// Require the specified class file from the libraries directory
|
||||||
|
require_once 'libraries/' . $className . '.php';
|
||||||
|
});
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
// DB Params
|
||||||
|
define('DBHOST', 'localhost');
|
||||||
|
define('DBUSER', 'root');
|
||||||
|
define('DBPASS', '');
|
||||||
|
define('DBNAME', 'nomadmvc');
|
||||||
|
|
||||||
|
// App Root
|
||||||
|
define('APP_ROOT', dirname(dirname(__FILE__)));
|
||||||
|
|
||||||
|
// URL Root
|
||||||
|
define('URL_ROOT', 'https://routeeasemvc.local');
|
||||||
|
|
||||||
|
// Site Name
|
||||||
|
define('SITENAME', 'RouteEase MVC');
|
||||||
|
|
||||||
|
// App Version
|
||||||
|
/**
|
||||||
|
* TODO: make APP_VERSION a protected class
|
||||||
|
*/
|
||||||
|
define('APP_VERSION', '0.0.1');
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Pages Controller Class
|
||||||
|
*
|
||||||
|
* This class handles the main pages of the application.
|
||||||
|
*/
|
||||||
|
class Pages extends Controller {
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public function __construct(){
|
||||||
|
// Constructor logic (if any)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index Method
|
||||||
|
*
|
||||||
|
* Handles the homepage of the application.
|
||||||
|
*/
|
||||||
|
public function index(){
|
||||||
|
// Check if the user is logged in
|
||||||
|
if (isLoggedIn()) {
|
||||||
|
// Redirect to the posts index page
|
||||||
|
redirect('/posts/index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data for the view
|
||||||
|
$data = [
|
||||||
|
'title' => 'Home',
|
||||||
|
'description' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('pages/index', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* About Method
|
||||||
|
*
|
||||||
|
* Handles the about us page of the application.
|
||||||
|
*/
|
||||||
|
public function about(){
|
||||||
|
// Data for the view
|
||||||
|
$data = [
|
||||||
|
'title' => 'About Us',
|
||||||
|
'description' => '',
|
||||||
|
'version' => APP_VERSION,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('pages/about', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Posts Controller Class
|
||||||
|
*
|
||||||
|
* This class handles the functionality related to posts in the application.
|
||||||
|
*/
|
||||||
|
class Posts extends Controller {
|
||||||
|
private $postModel;
|
||||||
|
private $userModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
// Check if the user is logged in
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
// Redirect to the login page if not logged in
|
||||||
|
redirect('/users/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize models
|
||||||
|
$this->postModel = $this->model('Post');
|
||||||
|
$this->userModel = $this->model('User');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index Method
|
||||||
|
*
|
||||||
|
* Displays a list of posts.
|
||||||
|
*/
|
||||||
|
public function index() {
|
||||||
|
// Get all posts
|
||||||
|
$posts = $this->postModel->getPosts();
|
||||||
|
|
||||||
|
// Data for the view
|
||||||
|
$data = [
|
||||||
|
'posts' => $posts,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('/posts/index', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Method
|
||||||
|
*
|
||||||
|
* Displays a single post.
|
||||||
|
*
|
||||||
|
* @param int $id Post ID
|
||||||
|
*/
|
||||||
|
public function show($id) {
|
||||||
|
// Get post and user information
|
||||||
|
$post = $this->postModel->getPost($id);
|
||||||
|
$user = $this->userModel->getUserById($post->user_id);
|
||||||
|
|
||||||
|
// Data for the view
|
||||||
|
$data = [
|
||||||
|
'post' => $post,
|
||||||
|
'user' => $user,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('/posts/show', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Method
|
||||||
|
*
|
||||||
|
* Adds a new post.
|
||||||
|
*/
|
||||||
|
public function add() {
|
||||||
|
// Check if the form is submitted
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
// Sanitize input data
|
||||||
|
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
|
||||||
|
// Extract form data
|
||||||
|
$data = [
|
||||||
|
'title' => trim($_POST['title']),
|
||||||
|
'summary' => trim($_POST['summary']),
|
||||||
|
'body' => trim($_POST['body']),
|
||||||
|
'userId' => $_SESSION['userId'],
|
||||||
|
'titleErr' => '',
|
||||||
|
'summaryErr' => '',
|
||||||
|
'bodyErr' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validate form data
|
||||||
|
if (empty($data['title'])) {
|
||||||
|
$data['titleErr'] = 'Please enter a title.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['summary'])) {
|
||||||
|
$data['summaryErr'] = 'Please enter a summary.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['body'])) {
|
||||||
|
$data['bodyErr'] = 'Please enter a body.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (empty($data['titleErr']) && empty($data['summaryErr']) && empty($data['bodyErr'])) {
|
||||||
|
// Add post to the database
|
||||||
|
if ($this->postModel->addPost($data)) {
|
||||||
|
message('post_message', 'Your post has been added.', 'alert alert-success');
|
||||||
|
redirect('/posts/index');
|
||||||
|
} else {
|
||||||
|
die('Something went wrong.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Load the view with the specified data and errors
|
||||||
|
$this->view('/posts/add', $data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Display the form
|
||||||
|
$data = [
|
||||||
|
'title' => '',
|
||||||
|
'summary' => '',
|
||||||
|
'body' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('/posts/add', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit Method
|
||||||
|
*
|
||||||
|
* Edits an existing post.
|
||||||
|
*
|
||||||
|
* @param int $id Post ID
|
||||||
|
*/
|
||||||
|
public function edit($id) {
|
||||||
|
// Check if the form is submitted
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
// Sanitize input data
|
||||||
|
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
|
||||||
|
// Extract form data
|
||||||
|
$data = [
|
||||||
|
'id' => $id,
|
||||||
|
'title' => trim($_POST['title']),
|
||||||
|
'summary' => trim($_POST['summary']),
|
||||||
|
'body' => trim($_POST['body']),
|
||||||
|
'userId' => $_SESSION['userId'],
|
||||||
|
'titleErr' => '',
|
||||||
|
'summaryErr' => '',
|
||||||
|
'bodyErr' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validate form data
|
||||||
|
if (empty($data['title'])) {
|
||||||
|
$data['titleErr'] = 'Please enter a title.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['summary'])) {
|
||||||
|
$data['summaryErr'] = 'Please enter a summary.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['body'])) {
|
||||||
|
$data['bodyErr'] = 'Please enter a body.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (empty($data['titleErr']) && empty($data['summaryErr']) && empty($data['bodyErr'])) {
|
||||||
|
// Update post in the database
|
||||||
|
if ($this->postModel->updatePost($data)) {
|
||||||
|
message('post_message', 'Your post has been updated.', 'alert alert-success');
|
||||||
|
redirect('/posts/index');
|
||||||
|
} else {
|
||||||
|
die('Something went wrong.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Load the view with the specified data and errors
|
||||||
|
$this->view('/posts/edit', $data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Display the form with existing post data
|
||||||
|
$post = $this->postModel->getPost($id);
|
||||||
|
|
||||||
|
// Check if the user is authorized to edit the post
|
||||||
|
if ($post->user_id != $_SESSION['userId']) {
|
||||||
|
redirect('/posts/index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data for the view
|
||||||
|
$data = [
|
||||||
|
'id' => $id,
|
||||||
|
'title' => $post->title,
|
||||||
|
'summary' => $post->summary,
|
||||||
|
'body' => $post->body,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('/posts/edit', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete Method
|
||||||
|
*
|
||||||
|
* Deletes a post.
|
||||||
|
*
|
||||||
|
* @param int $id Post ID
|
||||||
|
*/
|
||||||
|
public function delete($id) {
|
||||||
|
// Check if the form is submitted
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
// Delete post from the database
|
||||||
|
if ($this->postModel->deletePost($id)) {
|
||||||
|
message('post_message', 'Your post has been removed.');
|
||||||
|
redirect('/posts/index');
|
||||||
|
} else {
|
||||||
|
die('Something went wrong');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Redirect to the posts index page if form is not submitted
|
||||||
|
redirect('/posts/index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Users Controller Class
|
||||||
|
*
|
||||||
|
* This class handles user-related functionality such as registration, login, and logout.
|
||||||
|
*/
|
||||||
|
class Users extends Controller {
|
||||||
|
private $userModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
// Initialize the user model
|
||||||
|
$this->userModel = $this->model('User');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Method
|
||||||
|
*
|
||||||
|
* Handles user registration.
|
||||||
|
*/
|
||||||
|
public function register() {
|
||||||
|
// Check if the form is submitted
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
// Sanitize input data
|
||||||
|
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
|
||||||
|
// Extract form data
|
||||||
|
$data = [
|
||||||
|
'username' => trim($_POST['username']),
|
||||||
|
'email' => trim($_POST['email']),
|
||||||
|
'password' => trim($_POST['password']),
|
||||||
|
'again' => trim($_POST['again']),
|
||||||
|
'usernameErr' => '',
|
||||||
|
'emailErr' => '',
|
||||||
|
'passErr' => '',
|
||||||
|
'againErr' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validate form data
|
||||||
|
if (empty($data['email'])) {
|
||||||
|
$data['emailErr'] = 'Please provide an email.';
|
||||||
|
} else {
|
||||||
|
if ($this->userModel->findUserByEmail($data['email'])) {
|
||||||
|
$data['emailErr'] = 'Email exists.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['username'])) {
|
||||||
|
$data['usernameErr'] = 'Please provide a valid username.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['password'])) {
|
||||||
|
$data['passErr'] = 'Please provide a valid password.';
|
||||||
|
} elseif (strlen($data['password']) < 6) {
|
||||||
|
$data['passErr'] = 'Please provide a password 6 or more characters in length.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['again'])) {
|
||||||
|
$data['againErr'] = 'Please confirm your password.';
|
||||||
|
} else {
|
||||||
|
if ($data['password'] != $data['again']) {
|
||||||
|
$data['passErr'] = 'Passwords do not match.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (empty($data['usernameErr']) && empty($data['emailErr']) &&
|
||||||
|
empty($data['passErr']) && empty($data['againErr'])) {
|
||||||
|
|
||||||
|
// Hash the password
|
||||||
|
$data['password'] = password_hash($data['password'], PASSWORD_BCRYPT);
|
||||||
|
|
||||||
|
// Register the user
|
||||||
|
if ($this->userModel->register($data)) {
|
||||||
|
message('reg_success', 'You are now registered and can login.', 'alert alert-success');
|
||||||
|
redirect('/users/login');
|
||||||
|
} else {
|
||||||
|
die('Something went wrong.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Load the view with the specified data and errors
|
||||||
|
$this->view('users/register', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Display the registration form
|
||||||
|
$data = [
|
||||||
|
'username' => '',
|
||||||
|
'email' => '',
|
||||||
|
'password' => '',
|
||||||
|
'again' => '',
|
||||||
|
'usernameErr' => '',
|
||||||
|
'emailErr' => '',
|
||||||
|
'passErr' => '',
|
||||||
|
'againErr' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('users/register', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login Method
|
||||||
|
*
|
||||||
|
* Handles user login.
|
||||||
|
*/
|
||||||
|
public function login() {
|
||||||
|
// Check if the form is submitted
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
// Sanitize input data
|
||||||
|
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
|
||||||
|
// Extract form data
|
||||||
|
$data = [
|
||||||
|
'email' => trim($_POST['email']),
|
||||||
|
'password' => trim($_POST['password']),
|
||||||
|
'emailErr' => '',
|
||||||
|
'passErr' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validate form data
|
||||||
|
if (empty($data['email'])) {
|
||||||
|
$data['emailErr'] = 'Please provide an email.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['password'])) {
|
||||||
|
$data['passErr'] = 'Please provide a valid password.';
|
||||||
|
} elseif (strlen($data['password']) < 6) {
|
||||||
|
$data['passErr'] = 'Please provide a password 6 or more characters in length.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the user exists
|
||||||
|
if ($this->userModel->findUserByEmail($data['email'])) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$data['emailErr'] = 'No user found.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (empty($data['emailErr']) && empty($data['passErr'])) {
|
||||||
|
// Attempt to log in the user
|
||||||
|
$loggedIn = $this->userModel->login($data['email'], $data['password']);
|
||||||
|
|
||||||
|
if ($loggedIn) {
|
||||||
|
$this->createUserSession($loggedIn);
|
||||||
|
} else {
|
||||||
|
$data['passErr'] = 'Password was incorrect.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Load the view with the specified data and errors
|
||||||
|
$this->view('users/login', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Display the login form
|
||||||
|
$data = [
|
||||||
|
// 'username' => '',
|
||||||
|
'email' => '',
|
||||||
|
'password' => '',
|
||||||
|
// 'usernameErr' => '',
|
||||||
|
'emailErr' => '',
|
||||||
|
'passErr' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Load the view with the specified data
|
||||||
|
$this->view('users/login', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* createUserSession Method
|
||||||
|
*
|
||||||
|
* Creates a user session upon successful login.
|
||||||
|
*
|
||||||
|
* @param object $user User object
|
||||||
|
*/
|
||||||
|
public function createUserSession($user) {
|
||||||
|
// Set session variables
|
||||||
|
$_SESSION['userId'] = $user->id;
|
||||||
|
$_SESSION['username'] = $user->name;
|
||||||
|
$_SESSION['userEmail'] = $user->email;
|
||||||
|
|
||||||
|
// Redirect to the posts index page
|
||||||
|
redirect('/posts/index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout Method
|
||||||
|
*
|
||||||
|
* Logs out the user.
|
||||||
|
*/
|
||||||
|
public function logout() {
|
||||||
|
// Unset session variables
|
||||||
|
unset($_SESSION['userId']);
|
||||||
|
unset($_SESSION['username']);
|
||||||
|
unset($_SESSION['userEmail']);
|
||||||
|
|
||||||
|
// Redirect to the login page
|
||||||
|
redirect('/users/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Start Session
|
||||||
|
*
|
||||||
|
* Start the PHP session.
|
||||||
|
*/
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message Function
|
||||||
|
*
|
||||||
|
* Set or display a flash message.
|
||||||
|
*
|
||||||
|
* @param string $name Name of the message session variable
|
||||||
|
* @param string $msg Message content
|
||||||
|
* @param string $class CSS class for styling the message (default: 'alert alert-primary')
|
||||||
|
*/
|
||||||
|
function message($name='', $msg='', $class='alert alert-primary') {
|
||||||
|
if (!empty($name)) {
|
||||||
|
if (!empty($msg) && empty($_SESSION[$name])) {
|
||||||
|
// Set the message and its class in the session
|
||||||
|
if (!empty($_SESSION[$name])) {
|
||||||
|
unset($_SESSION[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($_SESSION[$name . '_class'])) {
|
||||||
|
unset($_SESSION[$name . '_class']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION[$name] = $msg;
|
||||||
|
$_SESSION[$name . '_class'] = $class;
|
||||||
|
} elseif (empty($msg) && !empty($_SESSION[$name])) {
|
||||||
|
// Display the message and its class
|
||||||
|
$class = !empty($_SESSION[$name . '_class']) ? $_SESSION[$name . '_class'] : '';
|
||||||
|
echo '<div class="'. $class .'" id="route-msg">' . $_SESSION[$name] . '</div>';
|
||||||
|
|
||||||
|
// Clear the session variables
|
||||||
|
unset($_SESSION[$name]);
|
||||||
|
unset($_SESSION[$name . '_class']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is Logged In Function
|
||||||
|
*
|
||||||
|
* Check if a user is logged in.
|
||||||
|
*
|
||||||
|
* @return bool Returns true if the user is logged in, false otherwise.
|
||||||
|
*/
|
||||||
|
function isLoggedIn() {
|
||||||
|
if (isset($_SESSION['userId'])) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Redirect Function
|
||||||
|
*
|
||||||
|
* Redirect the user to a specified page.
|
||||||
|
*
|
||||||
|
* @param string $page The page to redirect to
|
||||||
|
*/
|
||||||
|
function redirect($page) {
|
||||||
|
// Use the header function to perform the redirection
|
||||||
|
header('Location: ' . URL_ROOT . $page);
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Base Controller Class
|
||||||
|
*
|
||||||
|
* This class serves as the base controller, responsible for loading models and views.
|
||||||
|
*/
|
||||||
|
class Controller {
|
||||||
|
/**
|
||||||
|
* Load Model Method
|
||||||
|
*
|
||||||
|
* Loads and instantiates the specified model.
|
||||||
|
*
|
||||||
|
* @param string $model The name of the model to be loaded
|
||||||
|
* @return object An instance of the specified model
|
||||||
|
*/
|
||||||
|
public function model($model) {
|
||||||
|
// Require the model file
|
||||||
|
require_once '../app/models/' . $model . '.php';
|
||||||
|
|
||||||
|
// Instantiate the model
|
||||||
|
return new $model();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load View Method
|
||||||
|
*
|
||||||
|
* Loads the specified view file and passes data to it.
|
||||||
|
*
|
||||||
|
* @param string $view The name of the view file to be loaded
|
||||||
|
* @param array $data Data to be passed to the view (default: [])
|
||||||
|
* @param array $class Additional classes to be applied to the view (default: [])
|
||||||
|
*/
|
||||||
|
public function view($view, $data = [], $class = []) {
|
||||||
|
// Check if the view file exists
|
||||||
|
if (file_exists('../app/views/' . $view . '.php')) {
|
||||||
|
// Require the view file
|
||||||
|
require_once '../app/views/' . $view . '.php';
|
||||||
|
} else {
|
||||||
|
// View does not exist
|
||||||
|
die('View does not exist');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* App Core Class
|
||||||
|
*
|
||||||
|
* This class creates the URL and loads the core controller.
|
||||||
|
* URL FORMAT - /controller/method/params
|
||||||
|
*/
|
||||||
|
class Core {
|
||||||
|
protected $currentController = 'Pages';
|
||||||
|
protected $currentMethod = 'index';
|
||||||
|
protected $params = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
// Get the URL
|
||||||
|
$url = $this->getUrl();
|
||||||
|
|
||||||
|
// Look in controllers for the first value
|
||||||
|
if (!empty($url[0])) {
|
||||||
|
if (file_exists('../app/controllers/' . ucwords($url[0]) . '.php')) {
|
||||||
|
// If exists, set as controller
|
||||||
|
$this->currentController = ucwords($url[0]);
|
||||||
|
// Unset 0 Index
|
||||||
|
unset($url[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Require the controller
|
||||||
|
require_once '../app/controllers/' . $this->currentController . '.php';
|
||||||
|
|
||||||
|
// Instantiate the controller class
|
||||||
|
$this->currentController = new $this->currentController;
|
||||||
|
|
||||||
|
// Check for the second part of the URL
|
||||||
|
if (isset($url[1])) {
|
||||||
|
// Check to see if the method exists in the controller
|
||||||
|
if (method_exists($this->currentController, $url[1])) {
|
||||||
|
$this->currentMethod = $url[1];
|
||||||
|
// Unset 1 index
|
||||||
|
unset($url[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get params
|
||||||
|
$this->params = $url ? array_values($url) : [];
|
||||||
|
|
||||||
|
// Call a callback with an array of params
|
||||||
|
call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get URL Method
|
||||||
|
*
|
||||||
|
* Gets the URL and prepares it for processing.
|
||||||
|
*
|
||||||
|
* @return array An array representing the URL
|
||||||
|
*/
|
||||||
|
public function getUrl() {
|
||||||
|
if (isset($_GET['url'])) {
|
||||||
|
$url = rtrim($_GET['url'], '/');
|
||||||
|
$url = filter_var($url, FILTER_SANITIZE_URL);
|
||||||
|
$url = explode('/', $url);
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PDO Database Class
|
||||||
|
*
|
||||||
|
* This class is responsible for connecting to the database, creating prepared statements,
|
||||||
|
* binding values, and returning rows and results.
|
||||||
|
*/
|
||||||
|
class Database {
|
||||||
|
private $host = DBHOST;
|
||||||
|
private $user = DBUSER;
|
||||||
|
private $pass = DBPASS;
|
||||||
|
private $dbname = DBNAME;
|
||||||
|
|
||||||
|
private $dbh; // PDO instance
|
||||||
|
private $stmt; // Prepared statement
|
||||||
|
private $error; // Error message
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
// Set DSN
|
||||||
|
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
|
||||||
|
$options = array(
|
||||||
|
PDO::ATTR_PERSISTENT => true,
|
||||||
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create PDO instance
|
||||||
|
try {
|
||||||
|
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$this->error = $e->getMessage();
|
||||||
|
echo $this->error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query Method
|
||||||
|
*
|
||||||
|
* Prepares a statement with the provided SQL query.
|
||||||
|
*
|
||||||
|
* @param string $sql The SQL query
|
||||||
|
*/
|
||||||
|
public function query($sql) {
|
||||||
|
$this->stmt = $this->dbh->prepare($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind Method
|
||||||
|
*
|
||||||
|
* Binds a value to a parameter in the prepared statement.
|
||||||
|
*
|
||||||
|
* @param mixed $param The parameter to bind
|
||||||
|
* @param mixed $value The value to bind
|
||||||
|
* @param string $type The data type (default: null)
|
||||||
|
*/
|
||||||
|
public function bind($param, $value, $type = null) {
|
||||||
|
if (is_null($type)) {
|
||||||
|
switch (true) {
|
||||||
|
case is_int($value):
|
||||||
|
$type = PDO::PARAM_INT;
|
||||||
|
break;
|
||||||
|
case is_bool($value):
|
||||||
|
$type = PDO::PARAM_BOOL;
|
||||||
|
break;
|
||||||
|
case is_null($value):
|
||||||
|
$type = PDO::PARAM_NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$type = PDO::PARAM_STR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stmt->bindValue($param, $value, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute Method
|
||||||
|
*
|
||||||
|
* Executes the prepared statement.
|
||||||
|
*
|
||||||
|
* @return bool Returns true on success, false on failure
|
||||||
|
*/
|
||||||
|
public function execute() {
|
||||||
|
return $this->stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ResultSet Method
|
||||||
|
*
|
||||||
|
* Gets the result set as an array of objects.
|
||||||
|
*
|
||||||
|
* @return array An array of objects representing the result set
|
||||||
|
*/
|
||||||
|
public function resultSet() {
|
||||||
|
$this->execute();
|
||||||
|
return $this->stmt->fetchAll(PDO::FETCH_OBJ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single Method
|
||||||
|
*
|
||||||
|
* Gets a single record as an object.
|
||||||
|
*
|
||||||
|
* @return object An object representing a single record
|
||||||
|
*/
|
||||||
|
public function single() {
|
||||||
|
$this->execute();
|
||||||
|
return $this->stmt->fetch(PDO::FETCH_OBJ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RowCount Method
|
||||||
|
*
|
||||||
|
* Gets the row count of the result set.
|
||||||
|
*
|
||||||
|
* @return int The number of rows affected by the last SQL statement
|
||||||
|
*/
|
||||||
|
public function rowCount() {
|
||||||
|
return $this->stmt->rowCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Post Class
|
||||||
|
*
|
||||||
|
* This class is responsible for handling post-related database operations.
|
||||||
|
*/
|
||||||
|
class Post {
|
||||||
|
private $db; // Database instance
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->db = new Database;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetPosts Method
|
||||||
|
*
|
||||||
|
* Fetches all posts from the database.
|
||||||
|
*
|
||||||
|
* @return array An array of post objects
|
||||||
|
*/
|
||||||
|
public function getPosts() {
|
||||||
|
$this->db->query('SELECT *, posts.id as postId,
|
||||||
|
users.id as userId,
|
||||||
|
posts.created_at as postCreated,
|
||||||
|
users.created_at as userCreated
|
||||||
|
FROM posts INNER JOIN users ON posts.user_id = users.id ORDER BY posts.created_at DESC');
|
||||||
|
|
||||||
|
$res = $this->db->resultSet();
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetPost Method
|
||||||
|
*
|
||||||
|
* Fetches a single post by its ID.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the post
|
||||||
|
* @return object An object representing a single post
|
||||||
|
*/
|
||||||
|
public function getPost($id) {
|
||||||
|
$this->db->query('SELECT * FROM posts WHERE id = :id');
|
||||||
|
$this->db->bind(':id', $id);
|
||||||
|
|
||||||
|
$row = $this->db->single();
|
||||||
|
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddPost Method
|
||||||
|
*
|
||||||
|
* Inserts a new post into the database.
|
||||||
|
*
|
||||||
|
* @param array $data An associative array containing post data
|
||||||
|
* @return bool Returns true on success, false on failure
|
||||||
|
*/
|
||||||
|
public function addPost($data) {
|
||||||
|
$this->db->query('INSERT INTO posts (user_id, title, summary, body) VALUES(:userId, :title, :summary, :body)');
|
||||||
|
|
||||||
|
$this->db->bind(':userId', $data['userId']);
|
||||||
|
$this->db->bind(':title', $data['title']);
|
||||||
|
$this->db->bind(':summary', $data['summary']);
|
||||||
|
$this->db->bind(':body', $data['body']);
|
||||||
|
|
||||||
|
if ($this->db->execute()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UpdatePost Method
|
||||||
|
*
|
||||||
|
* Updates an existing post in the database.
|
||||||
|
*
|
||||||
|
* @param array $data An associative array containing post data
|
||||||
|
* @return bool Returns true on success, false on failure
|
||||||
|
*/
|
||||||
|
public function updatePost($data) {
|
||||||
|
$this->db->query('UPDATE posts SET title=:title, summary=:summary, body=:body WHERE id=:id');
|
||||||
|
|
||||||
|
$this->db->bind(':id', $data['id']);
|
||||||
|
$this->db->bind(':title', $data['title']);
|
||||||
|
$this->db->bind(':summary', $data['summary']);
|
||||||
|
$this->db->bind(':body', $data['body']);
|
||||||
|
|
||||||
|
if ($this->db->execute()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DeletePost Method
|
||||||
|
*
|
||||||
|
* Deletes a post from the database by its ID.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the post
|
||||||
|
* @return bool Returns true on success, false on failure
|
||||||
|
*/
|
||||||
|
public function deletePost($id) {
|
||||||
|
$this->db->query('DELETE FROM posts WHERE id = :id');
|
||||||
|
$this->db->bind(':id', $id);
|
||||||
|
|
||||||
|
if ($this->db->execute()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* User Class
|
||||||
|
*
|
||||||
|
* This class is responsible for handling user-related database operations.
|
||||||
|
*/
|
||||||
|
class User {
|
||||||
|
private $db; // Database instance
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->db = new Database;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetUserById Method
|
||||||
|
*
|
||||||
|
* Fetches a user by their ID.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the user
|
||||||
|
* @return object An object representing the user
|
||||||
|
*/
|
||||||
|
public function getUserById($id) {
|
||||||
|
$this->db->query('SELECT * FROM users WHERE id = :id');
|
||||||
|
$this->db->bind(':id', $id);
|
||||||
|
|
||||||
|
$row = $this->db->single();
|
||||||
|
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FindUserByEmail Method
|
||||||
|
*
|
||||||
|
* Checks if a user with the given email exists.
|
||||||
|
*
|
||||||
|
* @param string $email The email of the user
|
||||||
|
* @return bool Returns true if the user exists, false otherwise
|
||||||
|
*/
|
||||||
|
public function findUserByEmail($email) {
|
||||||
|
$this->db->query('SELECT * FROM users WHERE email = :email');
|
||||||
|
$this->db->bind(':email', $email);
|
||||||
|
|
||||||
|
$row = $this->db->single();
|
||||||
|
|
||||||
|
if ($this->db->rowCount() > 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Method
|
||||||
|
*
|
||||||
|
* Registers a new user in the database.
|
||||||
|
*
|
||||||
|
* @param array $data An associative array containing user data
|
||||||
|
* @return bool Returns true on success, false on failure
|
||||||
|
*/
|
||||||
|
public function register($data) {
|
||||||
|
$this->db->query('INSERT INTO users (name, email, password) VALUES(:name, :email, :password)');
|
||||||
|
|
||||||
|
$this->db->bind(':name', $data['username']);
|
||||||
|
$this->db->bind(':email', $data['email']);
|
||||||
|
$this->db->bind(':password', $data['password']);
|
||||||
|
|
||||||
|
if ($this->db->execute()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login Method
|
||||||
|
*
|
||||||
|
* Performs user login based on email and password.
|
||||||
|
*
|
||||||
|
* @param string $email The email of the user
|
||||||
|
* @param string $password The password of the user
|
||||||
|
* @return mixed Returns the user object on success, false on failure
|
||||||
|
*/
|
||||||
|
public function login($email, $password) {
|
||||||
|
$this->db->query('SELECT * FROM users WHERE email = :email');
|
||||||
|
$this->db->bind(':email', $email);
|
||||||
|
|
||||||
|
$row = $this->db->single();
|
||||||
|
|
||||||
|
$hashedPassword = $row->password;
|
||||||
|
if (password_verify($password, $hashedPassword)) {
|
||||||
|
return $row;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<script src="<?php echo URL_ROOT; ?>/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="<?php echo URL_ROOT; ?>/css/style.css">
|
||||||
|
<title><?php echo SITENAME; ?></title>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<?php require APP_ROOT . '/views/inc/navbar.php' ?>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-3">
|
||||||
|
<div class="container">
|
||||||
|
<!-- Brand Logo and Link -->
|
||||||
|
<a class="navbar-brand" href="<?php echo URL_ROOT ?>"><?php echo SITENAME ?></a>
|
||||||
|
|
||||||
|
<!-- Navbar Toggler Button for Responsive Design -->
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#topNavbarMain" aria-controls="topNavbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// TODO: Add bootstrap active class dynamically based on the current page
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!-- Navbar Links -->
|
||||||
|
<div class="collapse navbar-collapse" id="topNavbarMain">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
<!-- Home Link -->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="<?php echo URL_ROOT ?>">Home</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- About Link -->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="<?php echo URL_ROOT ?>/pages/about">About</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- Posts Link -->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="<?php echo URL_ROOT ?>/posts/">Posts</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- Right-aligned Navbar Links -->
|
||||||
|
<ul class="navbar-nav ml-auto">
|
||||||
|
<?php if (isset($_SESSION['userId'])) : ?>
|
||||||
|
<!-- Logout Link if User is Logged In -->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="<?php echo URL_ROOT ?>/users/logout">Logout</a>
|
||||||
|
</li>
|
||||||
|
<?php else : ?>
|
||||||
|
<!-- Register and Login Links if User is Not Logged In -->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="<?php echo URL_ROOT ?>/users/register">Register</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="<?php echo URL_ROOT ?>/users/login">Login</a>
|
||||||
|
</li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?php require APP_ROOT . '/views/inc/header.php'; ?>
|
||||||
|
<div class="jumbotron jumbotron-fluid text-center">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="display-3"><?PHP echo $data['title']; ?></h1>
|
||||||
|
<p class="lead"><?PHP echo $data['description'] ?></p>
|
||||||
|
<p class="lead"><span class="h5">Version: </span> <?PHP echo $data['version'] ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php require APP_ROOT . '/views/inc/footer.php'; ?>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php require APP_ROOT . '/views/inc/header.php'; ?>
|
||||||
|
<div class="jumbotron jumbotron-fluid text-center">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="display-3"><?php echo $data['title']; ?></h1>
|
||||||
|
<p class="lead"><?PHP echo $data['description'] ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php require APP_ROOT . '/views/inc/footer.php'; ?>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?PHP require APP_ROOT.'/views/inc/header.php' ?>
|
||||||
|
<a href="<?PHP echo URL_ROOT ?>/posts/index" class="btn btn-secondary"><i class="fa fa-backward"></i> Back</a>
|
||||||
|
<div class="card card-body bg-light mt-5">
|
||||||
|
<h2>Add Post</h2>
|
||||||
|
<p>Create a new post.</p>
|
||||||
|
<form action="<?PHP echo URL_ROOT ?>/posts/add" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title">Title: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="text" name="title" id="" class="form-control form-control-lg <?PHP echo (!empty($data['titleErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['title']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['titleErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="summary">Summary: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="text" name="summary" id="" class="form-control form-control-lg <?PHP echo (!empty($data['summaryErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['summary']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['summaryErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="body">Body: <sup class="is-invalid">*</sup></label>
|
||||||
|
<textarea name="body" id="" class="form-control form-control-lg <?PHP echo (!empty($data['bodyErr'])) ? 'is-invalid' : '' ?>"><?PHP echo $data['body']?></textarea>
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['bodyErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
<input type="submit" class="btn btn-primary" value="Submit">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?PHP require APP_ROOT.'/views/inc/footer.php' ?>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?PHP require APP_ROOT.'/views/inc/header.php' ?>
|
||||||
|
<a href="<?PHP echo URL_ROOT ?>/posts/index" class="btn btn-secondary"><i class="fa fa-backward"></i> Back</a>
|
||||||
|
<div class="card card-body bg-light mt-5">
|
||||||
|
<h2>Edit Post</h2>
|
||||||
|
<p>Create a new post.</p>
|
||||||
|
<form action="<?PHP echo URL_ROOT ?>/posts/edit/<?PHP echo $data['id'] ?>" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title">Title: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="text" name="title" id="" class="form-control form-control-lg <?PHP echo (!empty($data['titleErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['title']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['titleErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="summary">Summary: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="text" name="summary" id="" class="form-control form-control-lg <?PHP echo (!empty($data['summaryErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['summary']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['summaryErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="body">Body: <sup class="is-invalid">*</sup></label>
|
||||||
|
<textarea name="body" id="" class="form-control form-control-lg <?PHP echo (!empty($data['bodyErr'])) ? 'is-invalid' : '' ?>"><?PHP echo $data['body']?></textarea>
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['bodyErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
<input type="submit" class="btn btn-primary" value="Submit">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?PHP require APP_ROOT.'/views/inc/footer.php' ?>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php require APP_ROOT . '/views/inc/header.php'; ?>
|
||||||
|
<?PHP echo message('post_message'); ?>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h1>Posts</h1>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<a href="<?PHP echo URL_ROOT; ?>/posts/add" class="btn btn-primary pull-right">
|
||||||
|
<i class="fa fa-pencil"></i> Add Post
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?PHP foreach ($data['posts'] as $post) : ?>
|
||||||
|
<div class="card card-body mb-3">
|
||||||
|
<h4 class="card-title"><?PHP echo $post->title ?></h4>
|
||||||
|
<div class="bg-light p-2 mb-3">
|
||||||
|
written by: <?PHP echo $post->name ?> on <?PHP echo $post->postCreated ?>
|
||||||
|
</div>
|
||||||
|
<p class="card-text"><?PHP echo $post->summary ?></p>
|
||||||
|
<a href="<?PHP echo URL_ROOT ?>/posts/show/<?PHP echo $post->postId ?>" class="btn btn-dark">Read More</a>
|
||||||
|
</div>
|
||||||
|
<?PHP endforeach; ?>
|
||||||
|
<?php require APP_ROOT . '/views/inc/footer.php'; ?>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?PHP require APP_ROOT.'/views/inc/header.php' ?>
|
||||||
|
|
||||||
|
<a href="<?PHP echo URL_ROOT ?>/posts/index" class="btn btn-secondary"><i class="fa fa-backward"></i> Back</a>
|
||||||
|
<div class="card card-body bg-light mt-5">
|
||||||
|
<h1><?PHP echo $data['post']->title ?></h1>
|
||||||
|
<div class="bg-secondary text-white p-2 mb-3">
|
||||||
|
Written by <?PHP echo $data['user']->name ?> on <?PHP echo $data['post']->created_at ?></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><?PHP echo $data['post']->body ?></p>
|
||||||
|
|
||||||
|
<?PHP if ($data['post']->user_id == $_SESSION['userId']) : ?>
|
||||||
|
<hr>
|
||||||
|
<a href="<?PHP echo URL_ROOT ?>/posts/edit/<?PHP echo $data['post']->id ?>" class="btn btn-dark"><i class="fa fa-edit"></i> Edit Post</a>
|
||||||
|
|
||||||
|
<form method="post" action="<?PHP echo URL_ROOT ?>/posts/delete/<?PHP echo $data['post']->id ?>" class="pull-right">
|
||||||
|
<input type="submit" value="Delete Post" class="btn btn-danger">
|
||||||
|
</form>
|
||||||
|
<?PHP endif;?>
|
||||||
|
|
||||||
|
<?PHP require APP_ROOT.'/views/inc/footer.php' ?>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?PHP require APP_ROOT.'/views/inc/header.php' ?>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mx-auto">
|
||||||
|
<div class="card card-body bg-light mt-5">
|
||||||
|
<?PHP echo message('reg_success') ?>
|
||||||
|
<h2>Login to your Account</h2>
|
||||||
|
<p>Fill in your information to continue.</p>
|
||||||
|
<form action="<?PHP echo URL_ROOT ?>/users/login" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="email" name="email" id="" class="form-control form-control-lg <?PHP echo (!empty($data['emailErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['email']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['emailErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="password" name="password" id="" class="form-control form-control-lg <?PHP echo (!empty($data['passErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['password']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['passErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<input type="submit" value="Login" class="btn btn-success btn-block" />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<a href="<?PHP echo URL_ROOT ?>/users/register" class="btn btn-light btn-block">Register</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?PHP require APP_ROOT.'/views/inc/footer.php' ?>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?PHP require APP_ROOT.'/views/inc/header.php' ?>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mx-auto">
|
||||||
|
<div class="card card-body bg-light mt-5">
|
||||||
|
<h2>Create an Account</h2>
|
||||||
|
<p>Fill out to Register</p>
|
||||||
|
<form action="<?PHP echo URL_ROOT ?>/users/register" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username">Username: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="text" name="username" id="" class="form-control form-control-lg <?PHP echo (!empty($data['usernameErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['username']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['usernameErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="text" name="email" id="" class="form-control form-control-lg <?PHP echo (!empty($data['emailErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['email']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['emailErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="password" name="password" id="" class="form-control form-control-lg <?PHP echo (!empty($data['passErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['password']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['passErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="again">Confirm: <sup class="is-invalid">*</sup></label>
|
||||||
|
<input type="password" name="again" id="" class="form-control form-control-lg <?PHP echo (!empty($data['againErr'])) ? 'is-invalid' : '' ?>" value="<?PHP echo $data['again']?>" />
|
||||||
|
<span class="invalid-feedback"><?PHP echo $data['againErr'] ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<input type="submit" value="Register" class="btn btn-success btn-block" />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<a href="<?PHP echo URL_ROOT ?>/users/login" class="btn btn-light btn-block">Already Registered? Login</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?PHP require APP_ROOT.'/views/inc/footer.php' ?>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
Options -Multiviews
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteBase /
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
|
||||||
|
</IfModule>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
require_once '../app/bootstrap.php';
|
||||||
|
|
||||||
|
// Init Core Library
|
||||||
|
$init = new Core;
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
# RouteEase MVC
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Welcome to RouteEaseMVC, a web application built with PHP that provides
|
||||||
|
a versatile platform for creating, managing, and sharing posts.
|
||||||
|
This project follows the MVC (Model-View-Controller) architecture,
|
||||||
|
ensuring a clean and organized codebase.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [RouteEase MVC](#routeease-mvc)
|
||||||
|
- [Description](#description)
|
||||||
|
- [Table of Contents](#table-of-contents)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Usage](#usage)
|
||||||
|
- [File Structure](#file-structure)
|
||||||
|
- [Code Documentation](#code-documentation)
|
||||||
|
- [Contributing](#contributing)
|
||||||
|
- [TODO: Lists](#todo-lists)
|
||||||
|
- [License](#license)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Clone the repository: `git clone https://github.com/bckelley/routeeasemvc.git`
|
||||||
|
2. Navigate to the project directory: `cd RouteEaseMVC`
|
||||||
|
3. Set up the configuration file: `config/config.php` with required values.
|
||||||
|
4. Ensure the following PHP and MySQL and Apache are installed.
|
||||||
|
a. PHP version 8.1
|
||||||
|
b. MySQL version 8.0
|
||||||
|
c. Apache version 2.4
|
||||||
|
5. Visit the project URL in your browser.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Setup Configuration
|
||||||
|
a. Open the `config/config.php` file and configure settings such
|
||||||
|
as database connection details and other constants.
|
||||||
|
2. Setup Database
|
||||||
|
a. Create a MySQL database based on the configured details in `config/config.php`.
|
||||||
|
b. Import the provided SQL file to set up the necessary tables and data.
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
- `config/`: Contains configuration files.
|
||||||
|
- `helpers/`: Includes helper functions for URL and sessions.
|
||||||
|
- `libraries/`: Core libraries with autoloading.
|
||||||
|
- `app/`: Application files including controllers, models, and views.
|
||||||
|
- `public/`: Publicly accessible files (CSS, JS, images).
|
||||||
|
- `README.md`: Project documentation.
|
||||||
|
- `LICENSE`: Project License.
|
||||||
|
|
||||||
|
## Code Documentation
|
||||||
|
|
||||||
|
- `Controller.php`: Base controller class.
|
||||||
|
- `Core.php`: Core class for URL handling and loading controllers.
|
||||||
|
- `Database.php`: PDO Database class for database operations.
|
||||||
|
- `Post.php`: Class handling post-related database operations.
|
||||||
|
- `User.php`: Class handling user-related database operations.
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you'd like to contribute to the project, please follow the standard procedures:
|
||||||
|
|
||||||
|
1. Fork the repository.
|
||||||
|
2. Create a new branch: `git checkout -b feature/new-feature`
|
||||||
|
3. Make your changes and commit them: `git commit -m '[Your feature commit message]'`
|
||||||
|
4. Push to the branch: `git push origin feature/new-feature`
|
||||||
|
5. Create a pull request.
|
||||||
|
|
||||||
|
## TODO: Lists
|
||||||
|
|
||||||
|
[TODO](.todo)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under a derivative of the [CC-BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) - see the [LICENSE](LICENSE) file for details.
|
||||||
Reference in New Issue
Block a user