From 226e63c9e55fd01aab9ac035c9fc5aa0413cf79e Mon Sep 17 00:00:00 2001 From: Brian Flowers Date: Fri, 23 Apr 2021 23:00:43 -0400 Subject: [PATCH] Initial commit --- COPYING | 661 +++++++++++++++++++++++++++ Makefile | 157 +++++++ README.md | 52 +++ appinfo/app.php | 4 + appinfo/info.xml | 28 ++ appinfo/routes.php | 18 + composer.json | 15 + css/admin.css | 51 +++ css/style.css | 118 +++++ img/app.svg | 64 +++ js/.admin.js.swp | Bin 0 -> 1024 bytes js/admin.js | 398 ++++++++++++++++ js/admin.js.save | 225 +++++++++ js/script.js | 74 +++ lib/Controller/PageController.php | 85 ++++ lib/Service/ConfigService.php | 26 ++ lib/Settings/Admin.php | 72 +++ lib/Settings/Section.php | 89 ++++ phpunit.integration.xml | 7 + phpunit.xml | 7 + preview.png | Bin 0 -> 90784 bytes templates/content/index.php | 1 + templates/index.php | 15 + templates/navigation/index.php | 10 + templates/settings.php | 29 ++ tests/Integration/AppTest.php | 29 ++ tests/Unit/Controller/PageControllerTest.php | 31 ++ tests/bootstrap.php | 19 + 28 files changed, 2285 insertions(+) create mode 100644 COPYING create mode 100644 Makefile create mode 100644 README.md create mode 100644 appinfo/app.php create mode 100644 appinfo/info.xml create mode 100644 appinfo/routes.php create mode 100644 composer.json create mode 100644 css/admin.css create mode 100644 css/style.css create mode 100644 img/app.svg create mode 100644 js/.admin.js.swp create mode 100644 js/admin.js create mode 100644 js/admin.js.save create mode 100644 js/script.js create mode 100644 lib/Controller/PageController.php create mode 100644 lib/Service/ConfigService.php create mode 100644 lib/Settings/Admin.php create mode 100644 lib/Settings/Section.php create mode 100644 phpunit.integration.xml create mode 100644 phpunit.xml create mode 100644 preview.png create mode 100644 templates/content/index.php create mode 100644 templates/index.php create mode 100644 templates/navigation/index.php create mode 100644 templates/settings.php create mode 100644 tests/Integration/AppTest.php create mode 100644 tests/Unit/Controller/PageControllerTest.php create mode 100644 tests/bootstrap.php diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/COPYING @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + 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 AGPL, see +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ada504f --- /dev/null +++ b/Makefile @@ -0,0 +1,157 @@ +# This file is licensed under the Affero General Public License version 3 or +# later. See the COPYING file. +# @author Bernhard Posselt +# @copyright Bernhard Posselt 2016 + +# Generic Makefile for building and packaging a Nextcloud app which uses npm and +# Composer. +# +# Dependencies: +# * make +# * which +# * curl: used if phpunit and composer are not installed to fetch them from the web +# * tar: for building the archive +# * npm: for building and testing everything JS +# +# If no composer.json is in the app root directory, the Composer step +# will be skipped. The same goes for the package.json which can be located in +# the app root or the js/ directory. +# +# The npm command by launches the npm build script: +# +# npm run build +# +# The npm test command launches the npm test script: +# +# npm run test +# +# The idea behind this is to be completely testing and build tool agnostic. All +# build tools and additional package managers should be installed locally in +# your project, since this won't pollute people's global namespace. +# +# The following npm scripts in your package.json install and update the bower +# and npm dependencies and use gulp as build system (notice how everything is +# run from the node_modules folder): +# +# "scripts": { +# "test": "node node_modules/gulp-cli/bin/gulp.js karma", +# "prebuild": "npm install && node_modules/bower/bin/bower install && node_modules/bower/bin/bower update", +# "build": "node node_modules/gulp-cli/bin/gulp.js" +# }, + +app_name=$(notdir $(CURDIR)) +build_tools_directory=$(CURDIR)/build/tools +source_build_directory=$(CURDIR)/build/artifacts/source +source_package_name=$(source_build_directory)/$(app_name) +appstore_build_directory=$(CURDIR)/build/artifacts/appstore +appstore_package_name=$(appstore_build_directory)/$(app_name) +npm=$(shell which npm 2> /dev/null) +composer=$(shell which composer 2> /dev/null) + +all: build + +# Fetches the PHP and JS dependencies and compiles the JS. If no composer.json +# is present, the composer step is skipped, if no package.json or js/package.json +# is present, the npm step is skipped +.PHONY: build +build: +ifneq (,$(wildcard $(CURDIR)/composer.json)) + make composer +endif +ifneq (,$(wildcard $(CURDIR)/package.json)) + make npm +endif +ifneq (,$(wildcard $(CURDIR)/js/package.json)) + make npm +endif + +# Installs and updates the composer dependencies. If composer is not installed +# a copy is fetched from the web +.PHONY: composer +composer: +ifeq (, $(composer)) + @echo "No composer command available, downloading a copy from the web" + mkdir -p $(build_tools_directory) + curl -sS https://getcomposer.org/installer | php + mv composer.phar $(build_tools_directory) + php $(build_tools_directory)/composer.phar install --prefer-dist + php $(build_tools_directory)/composer.phar update --prefer-dist +else + composer install --prefer-dist + composer update --prefer-dist +endif + +# Installs npm dependencies +.PHONY: npm +npm: +ifeq (,$(wildcard $(CURDIR)/package.json)) + cd js && $(npm) run build +else + npm run build +endif + +# Removes the appstore build +.PHONY: clean +clean: + rm -rf ./build + +# Same as clean but also removes dependencies installed by composer, bower and +# npm +.PHONY: distclean +distclean: clean + rm -rf vendor + rm -rf node_modules + rm -rf js/vendor + rm -rf js/node_modules + +# Builds the source and appstore package +.PHONY: dist +dist: + make source + make appstore + +# Builds the source package +.PHONY: source +source: + rm -rf $(source_build_directory) + mkdir -p $(source_build_directory) + tar cvzf $(source_package_name).tar.gz ../$(app_name) \ + --exclude-vcs \ + --exclude="../$(app_name)/build" \ + --exclude="../$(app_name)/js/node_modules" \ + --exclude="../$(app_name)/node_modules" \ + --exclude="../$(app_name)/*.log" \ + --exclude="../$(app_name)/js/*.log" \ + +# Builds the source package for the app store, ignores php and js tests +.PHONY: appstore +appstore: + rm -rf $(appstore_build_directory) + mkdir -p $(appstore_build_directory) + tar cvzf $(appstore_package_name).tar.gz ../$(app_name) \ + --exclude-vcs \ + --exclude="../$(app_name)/build" \ + --exclude="../$(app_name)/tests" \ + --exclude="../$(app_name)/Makefile" \ + --exclude="../$(app_name)/*.log" \ + --exclude="../$(app_name)/phpunit*xml" \ + --exclude="../$(app_name)/composer.*" \ + --exclude="../$(app_name)/js/node_modules" \ + --exclude="../$(app_name)/js/tests" \ + --exclude="../$(app_name)/js/test" \ + --exclude="../$(app_name)/js/*.log" \ + --exclude="../$(app_name)/js/package.json" \ + --exclude="../$(app_name)/js/bower.json" \ + --exclude="../$(app_name)/js/karma.*" \ + --exclude="../$(app_name)/js/protractor.*" \ + --exclude="../$(app_name)/package.json" \ + --exclude="../$(app_name)/bower.json" \ + --exclude="../$(app_name)/karma.*" \ + --exclude="../$(app_name)/protractor\.*" \ + --exclude="../$(app_name)/.*" \ + --exclude="../$(app_name)/js/.*" \ + +.PHONY: test +test: composer + $(CURDIR)/vendor/phpunit/phpunit/phpunit -c phpunit.xml + $(CURDIR)/vendor/phpunit/phpunit/phpunit -c phpunit.integration.xml diff --git a/README.md b/README.md new file mode 100644 index 0000000..902f1f1 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Homepage +Place this app in **nextcloud/apps/** + +## Building the app + +The app can be built by using the provided Makefile by running: + + make + +This requires the following things to be present: +* make +* which +* tar: for building the archive +* curl: used if phpunit and composer are not installed to fetch them from the web +* npm: for building and testing everything JS, only required if a package.json is placed inside the **js/** folder + +The make command will install or update Composer dependencies if a composer.json is present and also **npm run build** if a package.json is present in the **js/** folder. The npm **build** script should use local paths for build systems and package managers, so people that simply want to build the app won't need to install npm libraries globally, e.g.: + +**package.json**: +```json +"scripts": { + "test": "node node_modules/gulp-cli/bin/gulp.js karma", + "prebuild": "npm install && node_modules/bower/bin/bower install && node_modules/bower/bin/bower update", + "build": "node node_modules/gulp-cli/bin/gulp.js" +} +``` + + +## Publish to App Store + +First get an account for the [App Store](http://apps.nextcloud.com/) then run: + + make && make appstore + +The archive is located in build/artifacts/appstore and can then be uploaded to the App Store. + +## Running tests +You can use the provided Makefile to run all tests by using: + + make test + +This will run the PHP unit and integration tests and if a package.json is present in the **js/** folder will execute **npm run test** + +Of course you can also install [PHPUnit](http://phpunit.de/getting-started.html) and use the configurations directly: + + phpunit -c phpunit.xml + +or: + + phpunit -c phpunit.integration.xml + +for integration tests diff --git a/appinfo/app.php b/appinfo/app.php new file mode 100644 index 0000000..dcc258f --- /dev/null +++ b/appinfo/app.php @@ -0,0 +1,4 @@ + + + homepage + Homepage + Create simple homepages + + 0.0.29 + agpl + Brian Flowers + Homepage + workflow + http://git.slightlycyberpunk.com/ + + + + + + Homepage + homepage.page.index + + + + + OCA\Homepage\Settings\Section + OCA\Homepage\Settings\Admin + + diff --git a/appinfo/routes.php b/appinfo/routes.php new file mode 100644 index 0000000..0ac0341 --- /dev/null +++ b/appinfo/routes.php @@ -0,0 +1,18 @@ + OCA\Homepage\Controller\PageController->index() + * + * The controller class has to be registered in the application.php file since + * it's instantiated in there + */ +return [ + 'routes' => [ + ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], + ['name' => 'page#do_echo', 'url' => '/echo', 'verb' => 'POST'], + ['name' => 'page#updateLayout', 'url' => '/update', 'verb' => 'POST'], + ['name' => 'page#getTypes', 'url' => '/getTypes', 'verb' => 'GET'] +// ['name' => 'page#updateLayout', 'url' => '/update', 'verb' => 'GET'] + ] +]; diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4b185c8 --- /dev/null +++ b/composer.json @@ -0,0 +1,15 @@ +{ + "name": "Homepage", + "description": "Create simple homepages", + "type": "project", + "license": "AGPL", + "authors": [ + { + "name": "Brian Flowers" + } + ], + "require": {}, + "require-dev": { + "phpunit/phpunit": "^5.4" + } +} diff --git a/css/admin.css b/css/admin.css new file mode 100644 index 0000000..a8cd71d --- /dev/null +++ b/css/admin.css @@ -0,0 +1,51 @@ +td.linksList, td.iframeOptions { + padding-left: 2em; + margin-left: 1em; + background-color: #00002020; + border-radius: 0.1em; + border: 1px solid #00002040; + +} + +td.linksList input { + width: 49%; +} + +td.linksList button { + display: block; + width: 100%; +} + +#saveButton.success { + background-color: #00FF0080; + transition: background-color 2s; +} + +#saveButton { + transition: background-color 2s; +} + +td.iframeOptions { + padding-left: 2em; +} + +td.iframeOptions input { + width: 75%; +} + +td.iframeOptions .height { + width: 23%; +} + +.delete { + border-radius: 0.1em; + +} + +.short { + width: 3em; +} + +.long { + width: 98%; +} diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..35b291d --- /dev/null +++ b/css/style.css @@ -0,0 +1,118 @@ +#app { + width: 100%; +} + +/*h1 { + display: block; + width: 100%; + background-image: linear-gradient(#0000 0%, #CCC3 10%, #0005 30%, #0005 70%, #CCC3 90%, #0000 100%); + padding-left: 3%; + font-size: 2em; + height: 2em; + padding-top: 0.5em; + font-weight: bold; +}*/ + +h1 { + font-size: 3em; + font-weight: bold; + height: 2em; + padding: 0.5em; +} + +iframe { + width: 100%; +} + +#applist { +/*display: flex; +flex-flow: row wrap;*/ + position: absolute; + top: 4em; +/* border: 1px solid black; */ + width: 96%; + left: 2%; + padding: 0.5em; +} + + +.smbars { + padding: 0.5em; + display: inline-block; + border-radius: 0.1em; +} + +.smbars span { + vertical-align: top; + margin-left: 0.4em; + margin-top: 0.2em; + font-size: 1.2em; +} + +.smicons { + padding: 0.5em; + display: inline-block; + border-radius: 0.1em; +} + +.smicons span { + display: none; +} + +.lgbars { + padding: 1.5em; + display: inline-block; + border-radius: 0.1em; + border: 1px solid #777; +} + +.lgbars span { + vertical-align: top; + margin-left: 0.4em; + margin-top: 0.2em; + font-size: 1.2em; +} + +.lgicons { + padding: 1.5em; + display: inline-block; + border-radius: 0.1em; +} + +.lgicons span { + display: block; +} + +.fullw { + padding: 1.5em; + display: block; + border-radius: 0.1em; + width: 100%; + text-align: center; +} + +.fullw span { + vertical-align: top; + margin-left: 0.4em; + margin-top: 0.2em; + font-size: 1.2em; +} + +a.fullw , span.fullw{ + border: 1px solid #808080; +} + +.linksList { + font-weight: bold; +} + +#app-content-wrapper { + flex-flow: row wrap; +} + +#app-content-wrapper div { + min-width: 10em; + max-width: 100%; + /*border-right: 1px solid #808080;*/ + padding: 0.5em; +} diff --git a/img/app.svg b/img/app.svg new file mode 100644 index 0000000..96a1b9f --- /dev/null +++ b/img/app.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/js/.admin.js.swp b/js/.admin.js.swp new file mode 100644 index 0000000000000000000000000000000000000000..6775badd41c736ee2a4f57b8984d92ff30bc6d30 GIT binary patch literal 1024 zcmYc?$V<%2S1{HyVn6{LvJ4DG`S~R%f;c#NsTC#3Ir*h2IOJi%`elhl`sL;2`fv^U si3J74`WgATsRfDYsrp&P`iUvInR$9y#V|di^k@i-h5*$ -- "; + li.innerHTML += types[key].description; + ul.appendChild(li); + } + document.getElementById("descriptor").appendChild(ul); + document.getElementById("descriptor").innerHTML += "You can also define a minimum width. "+ + "This can be particularly useful for mobile browsers where percentages may make columns too narrow."; + for(var i = 0; i < state.count; i++) { + addBlock(state['type_'+i], state['title_'+i], state['mode_'+i], state['width_'+i]); + } + if(state.count == 0) { + addBlock(null, null, null, null); + } + document.getElementById("minWidth").value = state['minWidth']; + document.getElementById("addButton").onclick = function() { addBlock(null); }; + document.getElementById("saveButton").onclick = function() { submit(); }; +} + +function addBlock(type, name, mode, wdth) { + var count = parseInt(document.getElementById("count").value); + document.getElementById("count").value = count+1; + + var table = document.getElementById("homepageLayoutTable"); + var form = document.createElement("form"); + var row = document.createElement("tr"); + var cell = document.createElement("td"); + var typeSelect = document.createElement("select"); + typeSelect.setAttribute("name", "type_"+count); + typeSelect.onchange = typeChange; + var types = getTypes(); + var keys = Object.keys(types); + for(var i = 0; i < keys.length; i++) { + var obj = types[keys[i]]; + var option = document.createElement("option"); + option.value = obj.type; + option.innerHTML = obj.name; + typeSelect.appendChild(option); + } + typeSelect.value = type; + cell.appendChild(typeSelect); + row.appendChild(cell); + //form.appendChild(select); + + cell = document.createElement("td"); + var title = document.createElement("input"); + title.setAttribute("name", "title_"+count); + title.setAttribute("type", "text"); + title.classList.add("long"); + title.setAttribute("placeholder", "title"); + if( name !== null && typeof name !== 'undefined' ) { + title.value = name; + } + cell.appendChild(title); + row.appendChild(cell); + //form.appendChild(title); + + cell = document.createElement("td"); + var select = document.createElement("select"); + select.setAttribute("name", "mode_"+count); + select.setAttribute("id", "mode_"+count); + var modes = getModes("applist"); + var keys = Object.keys(modes); + for(var i = 0; i < keys.length; i++) { + var obj = modes[keys[i]]; + var option = document.createElement("option"); + option.value = obj.type; + option.innerHTML = obj.name; + select.appendChild(option); + } + select.value = mode; + cell.appendChild(select); + row.appendChild(cell); + //form.appendChild(select); + + cell = document.createElement("td"); + var width = document.createElement("input"); + width.setAttribute("name", "width_"+count); + width.setAttribute("type", "text"); + width.setAttribute("placeholder", "%"); + width.setAttribute("class", "short"); + if(wdth !== null && typeof wdth !== 'undefined' ) { + width.value = wdth; + } + cell.appendChild(width); + row.appendChild(cell); + + cell = document.createElement("td"); + var delbtn = document.createElement("button"); + delbtn.setAttribute("type", "button"); + delbtn.innerHTML = "X"; + delbtn.setAttribute("id", "delete_"+count); + delbtn.setAttribute("class", "delete"); + delbtn.onclick = deleteBlock; + cell.appendChild(delbtn); + row.appendChild(cell); + + table.appendChild(row); + typeSelect.onchange(); +} + +function getTypes() { +/* var retval = {}; + retval.applist = {type: "applist", name: "App List"}; + retval.links = {type: "links", name: "Link List"}; +// retval.text = {type: "text", name: "Plaintext content"}; + retval.iframe = {type: "iframe", name: "IFrame"}; + return retval;*/ + var json = $.ajax({ + method: "GET", + url: OC.generateUrl('/apps/homepage/getTypes'), + data: '', + dataType: "json", + contentType: "application/json", + async: false + }).responseText; + return JSON.parse(JSON.parse(json).types); +} + +function getModes(type) { + var retval = {}; + retval.smicons = {type: "smicons", name: "Small Icons"}; + retval.lgicons = {type: "lgicons", name: "Large Icons"}; + retval.smbars = {type: "smbars", name: "Small Bars"}; + retval.lgbars = {type: "lgbars", name: "Large Bars"}; + retval.fullw = {type: "fullw", name: "Full Width"}; + return retval; +} + +function typeChange() { + const state = JSON.parse(OCP.InitialState.loadState('Homepage', 'state')); + var count = this.getAttribute("name").split("_")[1]; + var icount = 0; + + // Reset any previously disable attributes or opened options rows + document.getElementById("mode_"+count).removeAttribute("disabled"); + var opts = document.getElementsByClassName("options_"+count); + for(var i = 0; i < opts.length; i++) { + opts[i].style.display = "none"; + } + + if(this.value == "links") { + if(document.getElementById("options_"+count+"_links") != null) { + document.getElementById("options_"+count+"_links").style.display = "table-row"; + return; + } + var linksRow = document.createElement("tr"); + var linksCell = document.createElement("td"); + linksCell.setAttribute("colspan", 5); + linksCell.setAttribute("class", "linksList"); + linksRow.classList.add("options_"+count); + linksRow.setAttribute("id", "options_"+count+"_links"); + linksRow.appendChild(linksCell); + var row = this.parentElement.parentElement; + if(row.nextSibling != null) { + row.parentElement.insertBefore(linksRow, row.nextSibling); + } else { + row.parentElement.appendChild(linksRow); + } + +console.log("count: "+count); +console.log(state); + var icount = 0; + for(var i = 0; i < state['count']; i++) { +console.log(i); +// icount++; + if(typeof state['links_'+count+'_title_'+i] == 'undefined' || (state["links_"+count+"_title_"+i] == "" && state["links_"+count+"_url_"+i] == "")) { +// icount--; + continue; + } +console.log("icnt: "+icount); + var title = document.createElement("input"); + title.setAttribute("type", "text"); + title.setAttribute("name", "links_"+count+"_title_"+icount); + title.setAttribute("value", state["links_"+count+"_title_"+i]); + linksCell.appendChild(title); + + var url = document.createElement("input"); + url.setAttribute("type", "text"); + url.setAttribute("name", "links_"+count+"_url_"+icount); + url.setAttribute("value", state["links_"+count+"_url_"+i]); + linksCell.appendChild(url); + + var br = document.createElement("br"); + linksCell.appendChild(br); + icount++; + } + + var title = document.createElement("input"); + title.setAttribute("type", "text"); + title.setAttribute("name", "links_"+count+"_title_"+icount); + title.setAttribute("placeholder", "Link Text"); + linksCell.appendChild(title); + + var url = document.createElement("input"); + url.setAttribute("type", "text"); + url.setAttribute("name", "links_"+count+"_url_"+icount); + url.setAttribute("placeholder", "URL"); + linksCell.appendChild(url); + + var add = document.createElement("button"); + add.innerHTML = "+"; + add.onclick = function() { addLink(linksCell); }; + add.setAttribute("type", "button"); + linksCell.appendChild(add); + } else if( this.value == "iframe" ) { + if(document.getElementById("options_"+count+"_iframe") != null) { + document.getElementById("options_"+count+"_iframe").style.display = "table-row"; + return; + } + document.getElementById("mode_"+count).setAttribute("disabled", true); + + var optionsRow = document.createElement("tr"); + var optionsCell = document.createElement("td"); + optionsCell.setAttribute("colspan", 5); + optionsCell.classList.add("iframeOptions"); + optionsRow.classList.add("options_"+count); + optionsRow.setAttribute("id", "options_"+count+"_iframe"); + + var url = document.createElement("input"); + url.setAttribute("type", "text"); + url.setAttribute("name", "url_"+count); + url.setAttribute("placeholder", "URL"); + if( state['url_'+count] != null) { + url.value = state['url_'+count]; + } + optionsCell.appendChild(url); + + var height = document.createElement("input"); + height.setAttribute("type", "text"); + height.setAttribute("name", "height_"+count); + height.classList.add("height"); + height.setAttribute("placeholder", "height"); + if( state['height_'+count] != null) { + height.value = state['height_'+count]; + } + optionsCell.appendChild(height); + +//console.log(row); + optionsRow.appendChild(optionsCell); + var row = this.parentElement.parentElement; +// row.parentElement.insertAfter(row, optionsRow); + row.parentElement.appendChild(optionsRow); +console.log(row); + } +} + +function deleteBlock() { + var count = document.getElementById("count").value; + var target = this.getAttribute("id").split("_")[1]; + + var row = document.getElementById("mode_"+target).parentElement.parentElement; + var next = row.nextSibling; +console.log(row); +console.log(next); + row.parentElement.removeChild(row); +console.log(next); + if(!next.contains(document.getElementById("mode_"+(target+1)))) { + var tmp = next.nextSibling; + next.parentElement.removeChild(next); + next = tmp; + } + + while( next != null ) { + var inputs = next.getElementsByTagName("input"); + var selects = next.getElementsByTagName("select"); + var buttons = next.getElementsByTagName("button"); + inputs = Array.from(inputs).concat(Array.from(selects)).concat(Array.from(buttons)); + for(var i = 0; i < next.classList; i++) { + var classArr = next.classList[i].split("_"); + if(classArr.length < 2) { continue; } + classArr[1] = parseInt(classArr[1])-1; + next.classList.remove(next.classList[i]); + next.classList.add(classArr.join("_")); + } + if(next.getAttribute("id") != null) { + var idArr = next.getAttribute("id").split("_"); + idArr[1] = parseInt(idArr[1])-1; + next.setAttribute("id", idArr.join("_")); + } + for(var i = 0; i < inputs.length; i++) { + if(inputs[i].name != null) { + var namearr = inputs[i].name.split("_"); + namearr[1] = parseInt(namearr[1])-1; + inputs[i].name = namearr.join("_"); + } + if(inputs[i].getAttribute("id") != null) { + var idarr = inputs[i].getAttribute("id").split("_"); + idarr[1] = parseInt(idarr[1])-1; + inputs[i].setAttribute("id", idarr.join("_")); + } + } + next = next.nextSibling; + } + + document.getElementsById("count").value = count-1; + return false; +} + +function addLink(linksCell) { + var btn = linksCell.getElementsByTagName("button")[0]; + var prev = btn.previousSibling; + var prevArr = prev.name.split("_"); + var count = prevArr[1]; + var icount = prevArr[3]; + + var br = document.createElement("br"); + linksCell.insertBefore(br, btn); + + var title = document.createElement("input"); + title.setAttribute("type", "text"); + title.setAttribute("name", "links_"+count+"_title_"+icount); + title.setAttribute("placeholder", "Link Text"); + prev.parentElement.insertBefore(title, btn); + + var url = document.createElement("input"); + url.setAttribute("type", "text"); + url.setAttribute("name", "links_"+count+"_url_"+icount); + url.setAttribute("placeholder", "URL"); + linksCell.insertBefore(url, btn); +} + +init(); + + + + + + + + + + + diff --git a/js/admin.js.save b/js/admin.js.save new file mode 100644 index 0000000..358aee1 --- /dev/null +++ b/js/admin.js.save @@ -0,0 +1,225 @@ + +//document.getElementById("requesttoken").value = oc_requesttoken; +//console.log(oc_requesttoken); + +function submit() { + console.log($('form#homepageLayoutForm').serialize()); + var dataArr = $('form#homepageLayoutForm').serializeArray(); + var dataObj = {}; + for(var i = 0; i < dataArr.length; i++) { + dataObj[dataArr[i].name] = dataArr[i].value; + } + console.log(JSON.stringify(dataObj)); + document.getElementById("saveButton").innerHTML = "Saving..."; + + $.ajax({ + method: "POST", + url: OC.generateUrl('/apps/homepage/update'), + data: JSON.stringify({'data': dataObj}), //JSON.stringify({'data': $('form#homepageLayoutForm').serializeArray()}), + success: function(data){ + document.getElementById("saveButton").innerHTML = "Saved!"; + document.getElementById("saveButton").classList.add("success"); + setTimeout(function(){ + document.getElementById("saveButton").innerHTML = "Save"; + document.getElementById("saveButton").classList.remove("success"); + }, 5000); + console.log(data); + }, + failure: function(){alert("failure!");}, + dataType: "json", + contentType : "application/json" + }); +} + +function init() { + const state = JSON.parse(OCP.InitialState.loadState('Homepage', 'state')); + for(var i = 0; i < state.count; i++) { + addBlock(state['type_'+i], state['title_'+i], state['mode_'+i], state['width_'+i]); + } + if(state.count == 0) { + addBlock(null, null, null, null); + } + document.getElementById("addButton").onclick = function() { addBlock(null); }; + document.getElementById("saveButton").onclick = function() { submit(); }; +} + +function addBlock(type, name, mode, wdth) { + var count = parseInt(document.getElementById("count").value); + document.getElementById("count").value = count+1; + + var table = document.getElementById("homepageLayoutTable"); + var form = document.createElement("form"); + var row = document.createElement("tr"); + var cell = document.createElement("td"); + var typeSelect = document.createElement("select"); + typeSelect.setAttribute("name", "type_"+count); + typeSelect.onchange = typeChange; + var types = getTypes(); + var keys = Object.keys(types); + for(var i = 0; i < keys.length; i++) { + var obj = types[keys[i]]; + var option = document.createElement("option"); + option.value = obj.type; + option.innerHTML = obj.name; + typeSelect.appendChild(option); + } + typeSelect.value = type; + cell.appendChild(typeSelect); + row.appendChild(cell); + //form.appendChild(select); + + cell = document.createElement("td"); + var title = document.createElement("input"); + title.setAttribute("name", "title_"+count); + title.setAttribute("type", "text"); + title.setAttribute("placeholder", "title"); + if( name !== null && typeof name !== 'undefined' ) { + title.value = name; + } + cell.appendChild(title); + row.appendChild(cell); + //form.appendChild(title); + + cell = document.createElement("td"); + var select = document.createElement("select"); + select.setAttribute("name", "mode_"+count); + var modes = getModes("applist"); + var keys = Object.keys(modes); + for(var i = 0; i < keys.length; i++) { + var obj = modes[keys[i]]; + var option = document.createElement("option"); + option.value = obj.type; + option.innerHTML = obj.name; + select.appendChild(option); + } + select.value = mode; + cell.appendChild(select); + row.appendChild(cell); + //form.appendChild(select); + + cell = document.createElement("td"); + var width = document.createElement("input"); + width.setAttribute("name", "width_"+count); + width.setAttribute("type", "text"); + width.setAttribute("placeholder", "%"); + if(wdth !== null && typeof wdth !== 'undefined' ) { + width.value = wdth; + } + cell.appendChild(width); + row.appendChild(cell); + + table.appendChild(row); + typeSelect.onchange(); +} + +function getTypes() { + var retval = {}; + retval.applist = {type: "applist", name: "App List"}; + retval.links = {type: "links", name: "Link List"}; + retval.text = {type: "text", name: "Plaintext content"}; + retval.iframe = {type: "iframe", name: "IFrame"}; + return retval; +} + +function getModes(type) { + var retval = {}; + retval.smicons = {type: "smicons", name: "Small Icons"}; + retval.lgicons = {type: "lgicons", name: "Large Icons"}; + retval.smbars = {type: "smbars", name: "Small Bars"}; + retval.lgbars = {type: "lgbars", name: "Large Bars"}; + retval.fullw = {type: "fullw", name: "Full Width"}; + return retval; +} + +function typeChange() { + const state = JSON.parse(OCP.InitialState.loadState('Homepage', 'state')); + var count = this.getAttribute("name").split("_")[1]; + + if(this.value == "links") { + var linksRow = document.createElement("tr"); + var linksCell = document.createElement("td"); + linksCell.setAttribute("colspan", 4); + linksCell.setAttribute("class", "linksList"); + var row = this.parentElement.parentElement; + if(row.nextSibling != null) { + row.parentElement.insertBefore(linksCell, row.nextSibl); + } else { + row.parentElement.appendChild(linksCell); + } + + for(var i = 0; typeof state["links_"+count+"_title_"+i] != 'undefined'; i++) { + icount = i; + var title = document.createElement("input"); + title.setAttribute("type", "text"); + title.setAttribute("name", "links_"+count+"_title_"+i); + //title.setAttribute("placeholder", "Link Text"); + title.setAttribute("value", state["links_"+count+"_title_"+i]); + linksCell.appendChild(title); + + var url = document.createElement("input"); + url.setAttribute("type", "text"); + url.setAttribute("name", "links_"+count+"_url_"+i); + //url.setAttribute("placeholder", "URL"); + url.setAttribute("value", state["links_"+count+"_url_"+i]); + linksCell.appendChild(url); + + var br = document.createElement("br"); + linksCell.appendChild(br); + } + icount=i; + + var title = document.createElement("input"); + title.setAttribute("type", "text"); + title.setAttribute("name", "links_"+count+"_title_"+icount); + title.setAttribute("placeholder", "Link Text"); + linksCell.appendChild(title); + + var url = document.createElement("input"); + url.setAttribute("type", "text"); + url.setAttribute("name", "links_"+count+"_url_"+icount); + url.setAttribute("placeholder", "URL"); + linksCell.appendChild(url); + + var add = document.createElement("button"); + add.innerHTML = "+"; + add.onclick = function() { addLink(linksCell); }; + add.setAttribute("type", "button"); + linksCell.appendChild(add); + } +} + +function addLink(linksCell) { + var btn = linksCell.getElementsByTagName("button")[0]; + var prev = btn.previousSibling; + var prevArr = prev.name.split("_"); + var count = prevArr[1]; + var icount = prevArr[3]; + + var br = document.createElement("br"); + linksCell.insertBefore(br, btn); + + var title = document.createElement("input"); + title.setAttribute("type", "text"); + title.setAttribute("name", "links_"+count+"_title_"+icount); + title.setAttribute("placeholder", "Link Text"); + prev.parentElement.insertBefore(title, btn); + + var url = document.createElement("input"); + url.setAttribute("type", "text"); + url.setAttribute("name", "links_"+count+"_url_"+icount); + url.setAttribute("placeholder", "URL"); + linksCell.insertBefore(url, btn); +} + +init(); + + + + + + + + + + + diff --git a/js/script.js b/js/script.js new file mode 100644 index 0000000..064f809 --- /dev/null +++ b/js/script.js @@ -0,0 +1,74 @@ +function populateApps(mode) { + var appElems = document.getElementById("appmenu").children; + var appDiv = document.createElement("div"); + for(var i = 0; i < appElems.length; i++) { + if(appElems[i].getAttribute("class") == "menutoggle") { + continue; + } + var appBox = document.createElement("button"); + appBox.innerHTML = appElems[i].innerHTML; + appBox.setAttribute("class", mode); + appDiv.appendChild(appBox); + } + return appDiv; +} + +function populateLinks(mode, count, state) { + var linkDiv = document.createElement("div"); + linkDiv.classList.add("linksList"); + for(var i = 0; typeof state['links_'+count+'_title_'+i] != 'undefined'; i++) { + if(state['links_'+count+'_title_'+i] == "" && state['links_'+count+'_url_'+i] == "") { + continue; + } + + if(state['links_'+count+'_url_'+i] !== "") { + var link = document.createElement("a"); + link.href = state['links_'+count+'_url_'+i]; + } else { + var link = document.createElement("span"); + } + link.innerHTML = ""+state['links_'+count+'_title_'+i]+""; + link.setAttribute("class", mode); + linkDiv.appendChild(link); + } + return linkDiv; +} + +function populateIframe(count, state) { + var iframeDiv = document.createElement("iframe"); + iframeDiv.setAttribute("src", state['url_'+count]); + iframeDiv.style.height = state['height_'+count]; + return iframeDiv; +} + +function init() { + const state = JSON.parse(OCP.InitialState.loadState('Homepage', 'state')); + for(var i = 0; i < state.count; i++) { + addBlock(state['type_'+i], state['title_'+i], state['mode_'+i], state['width_'+i], i, state); + } +} + +function addBlock(type, title, mode, width, count, state) { + var section = document.createElement("div"); + section.style.width = width+"%"; + section.style.minWidth = state['minWidth']; + var header = document.createElement("h1"); + header.innerHTML = title; + section.appendChild(header); + + switch(type) { + case 'applist': + section.appendChild(populateApps(mode)); + break; + case 'links': + section.appendChild(populateLinks(mode, count, state)); + break; + case 'iframe': + section.appendChild(populateIframe(count, state)) + break; + } + + document.getElementById("app-content-wrapper").appendChild(section); +} + +init(); diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php new file mode 100644 index 0000000..8749d60 --- /dev/null +++ b/lib/Controller/PageController.php @@ -0,0 +1,85 @@ +userId = $UserId; + $this->config = $config; + $this->stateService = $initialStateService; + } + + /** + * CAUTION: the @Stuff turns off security checks; for this page no admin is + * required and no CSRF check. If you don't know what CSRF is, read + * it up in the docs or you might create a security hole. This is + * basically the only required method to add this exemption, don't + * add it to any other method if you don't exactly know what it does + * + * @NoAdminRequired + * @NoCSRFRequired + */ + public function index() { + if(class_exists('\\OCP\\AppFramework\\Http\\EmptyContentSecurityPolicy')) { + $manager = \OC::$server->getContentSecurityPolicyManager(); + $policy = new \OCP\AppFramework\Http\EmptyContentSecurityPolicy(); + $policy->addAllowedFrameDomain('\'self\''); + $manager->addDefaultPolicy($policy); + } + + $data = json_decode($this->config->getAppValue('data')); + $this->stateService->provideInitialState('Homepage', 'state', json_encode($data)); + return new TemplateResponse('homepage', 'index'); // templates/index.php + } + + public function updateLayout($data) { + $types = json_decode(str_replace(Array("\n", "\t"), "", $typesJSON)); + $old = $this->config->getAppValue("data"); + $this->config->setAppValue("data", json_encode($data)); + return array('status' => 'success', 'old' => json_decode($old), 'new' => $data); + } + + public function getTypes() { + return array('status' => 'success', 'types' => str_replace(array("\t", "\n"), "", $this->typesJSON)); + } +} diff --git a/lib/Service/ConfigService.php b/lib/Service/ConfigService.php new file mode 100644 index 0000000..e061ef0 --- /dev/null +++ b/lib/Service/ConfigService.php @@ -0,0 +1,26 @@ +config = $config; + $this->appName = $appName; + } + + public function getAppValue($key) { + return $this->config->getAppValue($this->appName, $key); + } + + public function setAppValue($key, $value) { + $this->config->setAppValue($this->appName, $key, $value); + } + +} + diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php new file mode 100644 index 0000000..fd6948e --- /dev/null +++ b/lib/Settings/Admin.php @@ -0,0 +1,72 @@ + + * + * @author Joas Schilling + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Homepage\Settings; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\IURLGenerator; +use OCP\Settings\ISettings; +use \OCA\Homepage\Service\ConfigService; +use OCP\IInitialStateService; + +class Admin implements ISettings { + + /** @var IURLGenerator */ + protected $url; + + private $appConfig; + private $stateservice; + + public function __construct(IURLGenerator $url, ConfigService $appConfig, IInitialStateService $initialStateService) { + $this->url = $url; + $this->appConfig = $appConfig; + $this->stateservice = $initialStateService; + } + + /** + * @return TemplateResponse + */ + public function getForm() { + $data = json_decode($this->appConfig->getAppValue('data')); + $this->stateservice->provideInitialState('Homepage', 'state', json_encode($data)); + return new TemplateResponse('homepage', 'settings', ["data" => $data], 'blank'); + } + + /** + * @return string the section ID, e.g. 'sharing' + */ + public function getSection() { + return 'homepage'; + } + + /** + * @return int whether the form should be rather on the top or bottom of + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * + * E.g.: 70 + */ + public function getPriority() { + return 55; + } +} diff --git a/lib/Settings/Section.php b/lib/Settings/Section.php new file mode 100644 index 0000000..6df2081 --- /dev/null +++ b/lib/Settings/Section.php @@ -0,0 +1,89 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Homepage\Settings; + +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\Settings\IIconSection; + +class Section implements IIconSection { + + /** @var IL10N */ + private $l; + + /** @var IURLGenerator */ + private $url; + + /** + * @param IURLGenerator $url + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) { + $this->url = $url; + $this->l = $l; + } + + /** + * returns the relative path to an 16*16 icon describing the section. + * e.g. '/core/img/places/files.svg' + * + * @returns string + * @since 12 + */ + public function getIcon() { + return $this->url->imagePath('homepage', 'app.svg'); + } + + /** + * returns the ID of the section. It is supposed to be a lower case string, + * e.g. 'ldap' + * + * @returns string + * @since 9.1 + */ + public function getID() { + return 'homepage'; + } + + /** + * returns the translated name as it should be displayed, e.g. 'LDAP / AD + * integration'. Use the L10N service to translate it. + * + * @return string + * @since 9.1 + */ + public function getName() { + return $this->l->t('Homepage'); + } + + /** + * @return int whether the form should be rather on the top or bottom of + * the settings navigation. The sections are arranged in ascending order of + * the priority values. It is required to return a value between 0 and 99. + * + * E.g.: 70 + * @since 9.1 + */ + public function getPriority() { + return 55; + } +} diff --git a/phpunit.integration.xml b/phpunit.integration.xml new file mode 100644 index 0000000..eae19f1 --- /dev/null +++ b/phpunit.integration.xml @@ -0,0 +1,7 @@ + + + + ./tests/Integration + + + diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..82c96d6 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,7 @@ + + + + ./tests/Unit + + + diff --git a/preview.png b/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..8624b3f3e1036c7527eb1dc0fd0f8c0f8ad16b18 GIT binary patch literal 90784 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 P>O&8V^!?#w96?9(5O}8v-uqHe`hD4Mp1h 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%0DE&BCeuJ~8QRJnxEl$%n}^6!w(|rt?0* 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

EQDOIm3nxj#6(d9PVbX5%uQTQ_@X+N+Pq zXlfD`6e8cUqI~jterQ;CnTf1*M-${PGhTDHi%p}@79eM62-f}3+8QYFGFJ}$CEp z{RS3>0YRY&D1+%EYIO)64@NQt-&9pwFPxq6q3i8Np)h!rk|Ok{nvWn}f<0RyUB4hc zafuvs7Q&KnrKqrAGEN6dj2Yh&zX>~C-9315!%M*YGk(p6E=C|1rb_#~UItPV%&Nr2 z#q_P@`&e)GNbqwe9EH&H&do)E{X2@#-!|O5(OgR2B~p{s=fNnR&+zp(%j1DEu}CP7 zdlY-OJ_L3I^|)w5Su0k(c=qHJX^58N!BZ}B?U08@!bfJ10gVMTr^i|%UH}=dmu=Bi zx`G1%{QOZ{(5+3bTuGHqwX|GiV8Lz_Ew-A~Gm)Ef%ne-&#Zzy4<84h};n4L25h0;9 zPU(Q3f}qT2{YlQIb3u7rm(efl**Sy#}vwAv!dh~qB=UL1!a5H5fd03%4us^}WkeQ_c9p}44zx*<0 zW(M(JS>t7aTThP5VuTw=+K!IS4|od}M`M@spbQ5bTN>%D8%M;CACJ;Pq>f8?wp{B% zQyvr>Uabd~8#YqFS3?Ew;2is>vY-BTOhdfFDP!lsJTUzGmYQQhH6V1WmD6?6IgQVT9=0chKml*q}Oqi(4b9@l6$J7P!c? z)lp84OL|CT(cl?n6;DRM)}SDRwih1O7TpNjozP3r4;Q*l8=IV5;7}VUJX%gULM;U#Brgz*Lg9$C&KkCRx`aOZQa#NvDVJ6{>AJ&!*|TZ(}qK-+;h!L z=p3X(YLWTF;=7T1NkzRWufj6+$kL7=BelBx(vx_KBi(rhR%$AFS*%AIHV6ec6hSLH z(dtDYAygcfn&;LoA zY0?rOTH(icmRH(oqVs7mwXU+ZvJzU6so2`Wn5L~9T`TJ(SX4Y1VdF(YUlzXw(xaU* z$nJv>54ziPQ?T<|_uf=sq7f{y$oDjngr2_0utGPx0p~YK7neEds}%&}bm^boBJ} z&}P1hijldN<828_@Molq^N=+jzWNgSluX;8De&x|X_^QeRHBFZLpQ#@1JbXMR@(pgd17BR^Eo=O$<~5qaRI{+|L5QWpWG%L* zhgRQ9X67^D-d+jyZpRiTyfYsbnU>eQ{$M`c9V1Ic{PGL< zb9X;|`kTmsf6D&zzHE#m68nki<({RzMeb^9+&Neu8+VCAhu5cK)YkzPq@Od3l5`H* zrrUQ2@nJrd#DAQwh_Q|SsdMxvzRKQ46gze_uXxjl&_{*rKNdVSnIM2$NOb9XZyLA8 zRZRk*kd4i9o{a@T%>jf9jkwv_nQ#BSIefCuCwH>j4L$P}j;T{pIp4Jrcefv3csgYn zUKSWfT`>wZqxO^(cNgj!Z{Hj#6p#RPwTP$y)0D*H$8QfXq2d!NjZI@D(MW$h-mNFs z@7N?Dx(Y`psfn!XjUwhi8;Kr#G5__eOIsWK5IHuM86IxxzHI!dISx_*>0rX>$bf%X zWKUNc)h`U+H&lJveWkjlJD*r^Dn7nvW1aG>v-2hn#V%%_q`SHhp$(o5FcZ}ycpND| zD6@yAd)c2aq(uH*DTzZmfzRvJ^z>*|)rM{X*d^?9vL&!+iUhYhD0Afw!p(#_`NI+g zDEvk~3}q;9Nb^p$>=3ccP16>2C%1y6SYS7~GQ{-)8s6W$ewG{IMh+Bpoyt3#ZOXuY zzW<7yofM|oW*ML)lvb>uCs$-g8bGu^-54bZOS(_$z`=uTEcup=Yyb7d-K_v2z!ij;u@%Q;Mxx+k@TaWO+nS@9-2btqheL{2%yOmm7tJ& zhzmv8=lPac06>>I)q!dY;JOi~9H*SBpV!=3c5kBxWxj1zt1kD{7yogaB_$$SFf)$EE-og?JciRJK={NrOd+`~Wk`ALr=zDUIKa*x6_5pZNj;Udfa4#sd8&N6r+<_0n>X(Z z3(IP{R5r7!4}U#96B>rw zQ;JNDOhs*pk_v+$O1KxgF5Bqz!k+L$Pd+fSSgRt02^l?IVMWF_gwIv^Sd#11&IO+; zNj9JVXbpurgUCL0eK5sCn#3xFd>t?MIZ6W3^CL1c#El=w@Xw-3&I)AK%i1-ENBp!a zJbZB0VPn1PrB~bQw-p=h%8umZ8=Q>{w@E#q6!+;R>u~w@Y2>kPTw{?@a=7y=a?!eo@(k3`oP?-brWPu#{PGK@s{&Sj=9Mp6MF#sE#QQTEwvGxojq_|#z?rNU)*=jP}u>a7__ zf;fdJRgdd9l4D_J_`q3IFni$gE(-#S6ZD)Z_3~r{;gkC?pM#xEgcSZZ>uhy}5371A z3vmT79dOvSoA~m%CeHA(lV(>5hg`(`jRJkupqNn8zTDIm8{l@p z8g}*ZV~|fgJy|}(*BsdoOxXp%(79R82f=dZP z+jyft@e7hUyR|KwQC9VgExS8+x`~mefX3CvxBQ&wakPBj7isdy?_8HNWuNg*t-h3x zPH($v8+4WSc4FNj*->)OC^=3z9+^t-ld|+i2PS52T0*zhZA;qaVPMPjiL zEg)GmH#a|M_D=Qm_kW%^Mm6scI;0;ZP+r-A8(sp5XFsJP5H(>`r-KkZozPy{mvdeq zDJ?B64+ZYjw{IWgWPXG!M+YH4CXt$1V1|6t#!6A)Z5FLf!pUbEorW?%^^FgCA`r0f zAv@5ksoiOsYpy$gSeDjUvtqE#^4?{ii4>lla-|Un4$}rZ8|%bXPa#-IrB{3)n!56x zhU+1C` zrlF~qpBPFW^V!rr51(_+jJJ%dSmWJNohmh|sHWX$%mzlWF_DI1g@$LIF zxp8KE3f>{Pw^8ZmkLwCj5k`XOdPFI6L$`QE9$JpA$T3ebmD%lybHf#^&}8g#SJ_*A zd;80GiNTf0J+MAu>zND>cXu<;%esAZFS?Zo4grnik)P(X3v#i~{Cp+{HVh0WqoTA~ zSYzm%=AVv^wnpoXuh4tjQDzL}pi{WU?c3JWn(wdqKq(7*<-y&1*b{&JA%(E)OVcI4 zu*RVZ8~~O!&OY41pw##jJ$OB2*+Y>{q8)76-~q*89vz)`9q?p=v6d4?#+FgBx26}i znZHJQC)@DRD06S^2rAN8Mvs;w&@2b7tD*J!?ZzvtLB48 zOcno4ZM!Ml2LV*965StJg=%=qu^#)5f9`EaS8cA_5b0BLY=K&^4U;=jVW>^vLr#Vv-?mL=xXGJMWRz>X>BdK_X3r4L7=f25)bF4AFJk}smEUu&!@Zy?NuyVGda~9 zT9yTbx^YOGXsQ`or)t~eA>A81B|1XR)VedtUa-?Lp+F%mGpPKmK%qdB+#t$nqS;-1@4;BCvYKf;+slI7 zkNNq91Nk8$#m5P`!SXi{9tqr`}pOd(5X1T8_&}Le7Wpy0p z$;i#DE_PXrl=GT0F=;Q<$-M9XF0duuvd5V^wuPd_cL%0zg>T^L{xG)pEms09F7GD8xblQ7>9mfuw!+E-)a-Ze?kvNCN#} zI9}x5=q=E)5ZXECsv03J*Ib<{fTTMjDg`b29Wq~(3J05c_G$V12H{03^JZ&xZ5w$Q z%;uj@cv4gB?Cb>(zIZ)hk9q_H!IH>iARb7lqTnO!>3KcLN-@AY5V~_o zueSO9YoB9_@5hVn62U0_l#*<(Tk{t@I*o>Ik3(f;=)*h)+i>yX0qSm%?s`KqpiO)! z>I``22o?VcXx@km=-`hoa~badty>Km^lv-jrsd5bSQTBb=&J-<{IiVnJLTklWtEHt z0gXLH3&f=IZI@k%;N?ifeddN;G}(I`ZNS5B%(R_x9zAKg?K0W1&9eK39aCST_`_E$DzZZ&gYg+C1$G;b9$BzFWN)7*AwEr&J z9sjfQVrg@->)XWZl0PuxcPGyJ?AT%Q!>es@>IbR&?-Sp`;J?@7`)TmsSPpW!F<;@A fcU`~qr|K_NI + +

+
+
+ inc('content/index')); ?> +
+
+
+ diff --git a/templates/navigation/index.php b/templates/navigation/index.php new file mode 100644 index 0000000..efa95c6 --- /dev/null +++ b/templates/navigation/index.php @@ -0,0 +1,10 @@ +
diff --git a/templates/settings.php b/templates/settings.php new file mode 100644 index 0000000..b53a23f --- /dev/null +++ b/templates/settings.php @@ -0,0 +1,29 @@ + + +
+
+

t('Homepage'));?>

+

Define your shit in the table below

+ + + +
+ + + + + + + + +
Block TypeBlock TitleDisplay TypeWidth
+ +
+
+
diff --git a/tests/Integration/AppTest.php b/tests/Integration/AppTest.php new file mode 100644 index 0000000..70395f6 --- /dev/null +++ b/tests/Integration/AppTest.php @@ -0,0 +1,29 @@ +container = $app->getContainer(); + } + + public function testAppInstalled() { + $appManager = $this->container->query('OCP\App\IAppManager'); + $this->assertTrue($appManager->isInstalled('homepage')); + } + +} diff --git a/tests/Unit/Controller/PageControllerTest.php b/tests/Unit/Controller/PageControllerTest.php new file mode 100644 index 0000000..f8cde26 --- /dev/null +++ b/tests/Unit/Controller/PageControllerTest.php @@ -0,0 +1,31 @@ +getMockBuilder('OCP\IRequest')->getMock(); + + $this->controller = new PageController( + 'homepage', $request, $this->userId + ); + } + + public function testIndex() { + $result = $this->controller->index(); + + $this->assertEquals('index', $result->getTemplateName()); + $this->assertTrue($result instanceof TemplateResponse); + } + +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..dfb7ae5 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,19 @@ +addValidRoot(OC::$SERVERROOT . '/tests'); + +// Fix for "Autoload path not allowed: .../homepage/tests/testcase.php" +\OC_App::loadApp('homepage'); + +if(!class_exists('PHPUnit_Framework_TestCase')) { + require_once('PHPUnit/Autoload.php'); +} + +OC_Hook::clear(); -- 1.8.3.1