Mes modifications de Vvveb après adaptation Docker
This commit is contained in:
commit
45060b7ded
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!php.ini
|
||||||
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
storage/compiled-templates/*
|
||||||
|
storage/cache/*
|
||||||
|
config/db.php
|
||||||
|
app/model/*
|
||||||
|
admin/model/*
|
||||||
|
public/page-cache/*
|
||||||
|
public/themes/*/*.html
|
||||||
|
!public/themes/*/src/*.html
|
||||||
|
public/admin/themes/*/*.html
|
||||||
|
!public/admin/themes/*/src/*.html
|
||||||
|
.codelite
|
||||||
|
vendor
|
||||||
|
node_modules
|
||||||
|
*.map.*
|
||||||
|
*.phprj
|
||||||
|
*.workspace
|
||||||
|
tinymce-dist
|
||||||
161
.htaccess
Normal file
161
.htaccess
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<IfModule !mod_authz_core.c>
|
||||||
|
<Files *.php>
|
||||||
|
Require all denied
|
||||||
|
</Files>
|
||||||
|
|
||||||
|
<Files index.php>
|
||||||
|
Order Allow,Deny
|
||||||
|
Allow from all
|
||||||
|
</Files>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule mod_authz_core.c>
|
||||||
|
<FilesMatch "\.(?i:php)$">
|
||||||
|
Require all denied
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<Files index.php>
|
||||||
|
Require all granted
|
||||||
|
</Files>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule dir_module>
|
||||||
|
DirectoryIndex index.php
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<Files "keycloak-callback.php">
|
||||||
|
Require all granted
|
||||||
|
</Files>
|
||||||
|
#<IfModule mod_headers.c>
|
||||||
|
#Header always set Content-Security-Policy "upgrade-insecure-requests;"
|
||||||
|
#</IfModule>
|
||||||
|
|
||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteBase /
|
||||||
|
|
||||||
|
# Redirect http to https
|
||||||
|
#RewriteCond %{HTTPS} !=on
|
||||||
|
#RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
|
||||||
|
|
||||||
|
#page cache
|
||||||
|
RewriteCond %{REQUEST_METHOD} !=POST
|
||||||
|
RewriteCond %{QUERY_STRING} !.*=.*
|
||||||
|
RewriteCond %{HTTP_COOKIE} !^.*(nocache|cart|user|admin).*$
|
||||||
|
#RewriteCond %{QUERY_STRING} !^.*(nocache|admin).*$
|
||||||
|
RewriteCond %{QUERY_STRING} !^.*(/admin).*$
|
||||||
|
RewriteCond %{DOCUMENT_ROOT}/public/page-cache/%{HTTP_HOST}/$1/index.html -f
|
||||||
|
RewriteRule ^(.*) /public/page-cache/%{HTTP_HOST}/$1/index.html [L]
|
||||||
|
RewriteCond %{DOCUMENT_ROOT}/public/page-cache/%{HTTP_HOST}/$1 -f
|
||||||
|
RewriteRule ^(.*) /public/page-cache/%{HTTP_HOST}/$1 [L]
|
||||||
|
#end page cache
|
||||||
|
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^ index.php [L]
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
#static files expiration
|
||||||
|
#ExpiresDefault A2592000 = 1 month in the future
|
||||||
|
#Cache-Control "max-age=2592000" = 1 month
|
||||||
|
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
|
||||||
|
Header unset ETag
|
||||||
|
Header set Connection keep-alive
|
||||||
|
|
||||||
|
<FilesMatch "\.(txt|xml|js)$">
|
||||||
|
Header set Cache-Control "max-age=2592000"
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<FilesMatch "\.(css)$">
|
||||||
|
Header set Cache-Control "max-age=2592000"
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav|mp4|m4v|ogg|webm|aac)$">
|
||||||
|
Header set Cache-Control "max-age=2592000"
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<FilesMatch "\.(jpg|jpeg|png|gif|swf|webp)$">
|
||||||
|
Header set Cache-Control "max-age=2592000"
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$">
|
||||||
|
Header set Access-Control-Allow-Origin "*"
|
||||||
|
</FilesMatch>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
#FileETag None
|
||||||
|
|
||||||
|
<IfModule mod_expires.c>
|
||||||
|
ExpiresActive On
|
||||||
|
ExpiresDefault A2592000
|
||||||
|
|
||||||
|
<FilesMatch "\.(txt|xml|js)$">
|
||||||
|
ExpiresDefault A2592000
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<FilesMatch "\.(css)$">
|
||||||
|
ExpiresDefault A2592000
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<FilesMatch "\.(ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav|mp4|m4v|ogg|webm|aac)$">
|
||||||
|
ExpiresDefault A2592000
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
<FilesMatch "\.(jpg|jpeg|png|gif|swf|webp)$">
|
||||||
|
ExpiresDefault A2592000
|
||||||
|
</FilesMatch>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#gzip to reduce response size
|
||||||
|
<IfModule mod_deflate.c>
|
||||||
|
<IfModule mod_setenvif.c>
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
|
||||||
|
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
|
||||||
|
</IfModule>
|
||||||
|
</IfModule>
|
||||||
|
<IfModule mod_filter.c>
|
||||||
|
AddOutputFilterByType DEFLATE "application/atom+xml" \
|
||||||
|
"application/javascript" \
|
||||||
|
"application/json" \
|
||||||
|
"application/ld+json" \
|
||||||
|
"application/manifest+json" \
|
||||||
|
"application/rdf+xml" \
|
||||||
|
"application/rss+xml" \
|
||||||
|
"application/schema+json" \
|
||||||
|
"application/vnd.geo+json" \
|
||||||
|
"application/vnd.ms-fontobject" \
|
||||||
|
"application/x-font-ttf" \
|
||||||
|
"application/x-javascript" \
|
||||||
|
"application/x-web-app-manifest+json" \
|
||||||
|
"application/xhtml+xml" \
|
||||||
|
"application/xml" \
|
||||||
|
"font/eot" \
|
||||||
|
"font/opentype" \
|
||||||
|
"image/bmp" \
|
||||||
|
"image/svg+xml" \
|
||||||
|
"image/vnd.microsoft.icon" \
|
||||||
|
"image/x-icon" \
|
||||||
|
"text/cache-manifest" \
|
||||||
|
"text/css" \
|
||||||
|
"text/html" \
|
||||||
|
"text/javascript" \
|
||||||
|
"text/plain" \
|
||||||
|
"text/vcard" \
|
||||||
|
"text/vnd.rim.location.xloc" \
|
||||||
|
"text/vtt" \
|
||||||
|
"text/x-component" \
|
||||||
|
"text/x-cross-domain-policy" \
|
||||||
|
"text/xml"
|
||||||
|
|
||||||
|
</IfModule>
|
||||||
|
<IfModule mod_mime.c>
|
||||||
|
AddEncoding gzip svgz
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
661
LICENSE
Normal file
661
LICENSE
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU 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.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
3
admin/.htaccess
Normal file
3
admin/.htaccess
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<IfModule dir_module>
|
||||||
|
DirectoryIndex index.php
|
||||||
|
</IfModule>
|
||||||
228
admin/admin-bar.php
Normal file
228
admin/admin-bar.php
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (! defined('V_VERSION')) {
|
||||||
|
die('Invalid request!');
|
||||||
|
}
|
||||||
|
//if (function_exists('printAdminBarMenu')) return;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
|
||||||
|
$menu = \Vvveb\config('admin-menu', []);
|
||||||
|
list($menu) = Vvveb\System\Event::trigger('Vvveb\Controller\Base','init-menu', $menu);
|
||||||
|
list($menu) = Vvveb\System\Event::trigger('admin-bar', 'menu', $menu);
|
||||||
|
list($top) = Vvveb\System\Event::trigger('admin-bar', 'top', []);
|
||||||
|
|
||||||
|
$template = Vvveb\getCurrentTemplate();
|
||||||
|
$url = Vvveb\getCurrentUrl();
|
||||||
|
$admin_path = Vvveb\adminPath() . 'index.php';
|
||||||
|
$params = ['module' => 'editor/editor', 'template' => $template, 'url' => $url];
|
||||||
|
$request = Vvveb\System\Core\Request::getInstance();
|
||||||
|
$name = $request->get['name'] ?? $request->get['slug'] ?? '';
|
||||||
|
$urlData = Vvveb\System\Routes::getUrlData($url);
|
||||||
|
$edit_url = isset($urlData['edit']) ? $admin_path . $urlData['edit'] : '';
|
||||||
|
|
||||||
|
if ($name) {
|
||||||
|
$params['name'] = urlencode($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($request->get['post_id'])) {
|
||||||
|
$params['post_id'] = $request->get['post_id'];
|
||||||
|
|
||||||
|
if ($edit_url) {
|
||||||
|
$edit_url .= '&post_id=' . $params['post_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($request->get['product_id'])) {
|
||||||
|
$params['product_id'] = $request->get['product_id'];
|
||||||
|
|
||||||
|
if ($edit_url) {
|
||||||
|
$edit_url .= '&product_id=' . $params['product_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$design_url = $admin_path . Vvveb\url($params, false, false);
|
||||||
|
$admin = \Vvveb\System\User\Admin :: current();
|
||||||
|
$profile_url = $admin_path . Vvveb\url(['module' => 'admin/user', 'admin_id' => $admin['admin_id']], false, false);
|
||||||
|
|
||||||
|
if (! function_exists('printAdminBarMenu')) {
|
||||||
|
function printAdminBarMenu($menu) {
|
||||||
|
foreach ($menu as $menuEntry) {
|
||||||
|
echo '<li>';
|
||||||
|
|
||||||
|
if (isset($menuEntry['url'])) {
|
||||||
|
echo '<a href="' . $menuEntry['url'] . '" ' . (isset($menuEntry['items']) ? 'class="has-submenu"' : '') . '>';
|
||||||
|
|
||||||
|
if (isset($menuEntry['icon']) && $menuEntry['icon']) {
|
||||||
|
echo '<i class="' . $menuEntry['icon'] . '"></i>';
|
||||||
|
} elseif (isset($menuEntry['icon-img']) && $menuEntry['icon-img']) {
|
||||||
|
echo '<img src="' . $menuEntry['icon-img'] . '">';
|
||||||
|
} else {
|
||||||
|
echo '<i></i>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $menuEntry['name'] . '</a>';
|
||||||
|
} else {
|
||||||
|
echo '<span>' . $menuEntry['name'] . '</span><hr/>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($menuEntry['items'])) {
|
||||||
|
echo '<ul class="submenu">';
|
||||||
|
printAdminBarMenu($menuEntry['items']);
|
||||||
|
echo '</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div id="vvveb-admin">
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li class="v-logo"><a href="https://www.vvveb.com" target="_blank"><div class="vvveb-logo"></div></a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://www.vvveb.com" target="_blank">
|
||||||
|
<i class="la la-home"></i><?php echo __('Vvveb Homepage'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://docs.vvveb.com" target="_blank">
|
||||||
|
<i class="la la-file-alt"></i><?php echo __('Documentation'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://github.com/givanz/Vvveb/discussions" target="_blank">
|
||||||
|
<i class="la la-sms"></i><?php echo __('Forums'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="<?php echo $admin_path; ?>"><i class="icon-pulse-outline"></i><?php echo __('Admin'); ?></a>
|
||||||
|
<ul>
|
||||||
|
<?php printAdminBarMenu($menu); ?>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $design_url; ?>"> <i class="la la-paint-brush"></i><?php echo __('Design page'); ?></a>
|
||||||
|
</li>
|
||||||
|
<?php if ($edit_url) { ?>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $edit_url; ?>"> <i class="la la-pencil-alt"></i><?php echo __('Edit page'); ?></a>
|
||||||
|
</li>
|
||||||
|
<?php } ?>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path . '?module=content/comments&status=0&type=post'; ?>">
|
||||||
|
<i class="la la-comments"></i><?php echo __('Comments'); ?></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path; ?>?module=tools/cache&action=delete">
|
||||||
|
<i class="icon-reload-circle-outline"></i>
|
||||||
|
<?php echo __('Clear cache'); ?></a>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path; ?>?module=tools/cache&action=asset" target="_blank">
|
||||||
|
<i class="la la-circle-notch"></i>
|
||||||
|
<?php echo __('Frontend assets cache'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path; ?>?module=tools/cache&action=template" target="_blank">
|
||||||
|
<i class="la la-circle-notch"></i><?php echo __('Compiled templates'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="<?php echo $admin_path; ?>?module=tools/cache&action=database" target="_blank">
|
||||||
|
<i class="la la-circle-notch"></i>
|
||||||
|
<?php echo __('Database'); ?></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path; ?>?module=tools/cache&action=image" target="_blank">
|
||||||
|
<i class="la la-circle-notch"></i>
|
||||||
|
<?php echo __('Image resize cache'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path; ?>?module=tools/cache&action=page" target="_blank">
|
||||||
|
<i class="la la-circle-notch"></i>
|
||||||
|
<?php echo __('Full page cache'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown-divider">
|
||||||
|
<hr />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path; ?>?module=tools/cache&action=delete" target="_blank">
|
||||||
|
<i class="la la-circle-notch"></i>
|
||||||
|
<?php echo __('All cache'); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<?php if ($top) { ?>
|
||||||
|
<li><div class="vr align-middle mx-1"> </div></li>
|
||||||
|
<?php
|
||||||
|
printAdminBarMenu($top);
|
||||||
|
} ?>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<ul class="float-end">
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $admin_path; ?>"><i class="la la-user"></i><?php echo $admin['display_name'] ?? ''; ?></a>
|
||||||
|
<ul style="right:0;">
|
||||||
|
<li><a href="<?php echo $profile_url; ?>"><i class="la la-edit"></i><?php echo __('Edit profile'); ?></a></li>
|
||||||
|
<li>
|
||||||
|
<form action="<?php echo $admin_path; ?>?module=user/login"
|
||||||
|
method="post" enctype="multipart/form-data" target="_blank">
|
||||||
|
<input type="hidden" name="csrf" data-v-csrf>
|
||||||
|
<input type="hidden" name="logout">
|
||||||
|
|
||||||
|
<button type="submit" value="logout" class="btn btn-light text-dark w-100">
|
||||||
|
|
||||||
|
<span class="loading d-none">
|
||||||
|
<span class="spinner-border spinner-border-sm align-middle" role="status" aria-hidden="true">
|
||||||
|
</span>
|
||||||
|
<span>Loading ...</span>...
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="button-text text-dark">
|
||||||
|
<i class="la la-sign-out-alt"></i><?php echo __('Log out'); ?>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<link href="<?php echo Vvveb\publicUrlPath(); ?>admin/default/css/admin-bar.css" rel="stylesheet">
|
||||||
|
<script>
|
||||||
|
window.addEventListener("load", (event) => {
|
||||||
|
if (VvvebTheme.ajax.siteContainer) {
|
||||||
|
VvvebTheme.ajax.siteContainer.push("#vvveb-admin");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
58
admin/component/admin.php
Normal file
58
admin/component/admin.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
use Vvveb\System\User\Admin as AdminUser;
|
||||||
|
|
||||||
|
class Admin extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'limit' => 1000,
|
||||||
|
'page' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $options = [];
|
||||||
|
|
||||||
|
public $cacheExpire = 0; //seconds
|
||||||
|
|
||||||
|
function cacheKey() {
|
||||||
|
// disable caching
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$results = AdminUser::current();
|
||||||
|
|
||||||
|
foreach (['avatar', 'cover'] as $image) {
|
||||||
|
if (isset($results[$image])) {
|
||||||
|
$results[$image]= Images::image($results[$image], 'admin');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
66
admin/component/comments.php
Normal file
66
admin/component/comments.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use Vvveb\Sql\CommentSQL;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Comments extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'language_id' => null,
|
||||||
|
'site_id' => null,
|
||||||
|
'status' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$comments = new CommentSQL();
|
||||||
|
|
||||||
|
$results = $comments->getAll($this->options) ?? [];
|
||||||
|
|
||||||
|
if (isset($results['comment'])) {
|
||||||
|
foreach ($results['comment'] as $id => &$comment) {
|
||||||
|
if (isset($comment['images'])) {
|
||||||
|
$comment['images'] = json_decode($comment['images'], 1);
|
||||||
|
|
||||||
|
foreach ($comment['images'] as &$image) {
|
||||||
|
$image = Images::image('comment', $image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($comment['image'])) {
|
||||||
|
$comment['images'][] = Images::image($comment['image'], 'comment');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
75
admin/component/languages.php
Normal file
75
admin/component/languages.php
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use function Vvveb\availableLanguages;
|
||||||
|
use function Vvveb\session;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
|
||||||
|
class Languages extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 1,
|
||||||
|
'limit' => 1000,
|
||||||
|
'status' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $options = [];
|
||||||
|
|
||||||
|
public $cacheExpire = 0; //seconds
|
||||||
|
|
||||||
|
function cacheKey() {
|
||||||
|
// disable caching
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$results = [];
|
||||||
|
$results['language'] = availableLanguages();
|
||||||
|
|
||||||
|
if ($results['language']) {
|
||||||
|
$results['current'] = $code = session('language', 'en');
|
||||||
|
|
||||||
|
if (! isset($results['language'][$code])) {
|
||||||
|
$results['current'] = $code = key($results['language']);
|
||||||
|
}
|
||||||
|
$language = $results['language'][$code] ?? [];
|
||||||
|
$results['active'] = [];
|
||||||
|
|
||||||
|
// if selected language not install default to english
|
||||||
|
if ($language) {
|
||||||
|
$results['active'] = [
|
||||||
|
'name' => $language['name'],
|
||||||
|
'code' => $language['code'],
|
||||||
|
'slug' => $language['slug'],
|
||||||
|
'id' => $language['language_id'],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
admin/component/news.php
Normal file
77
admin/component/news.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use function Vvveb\getUrl;
|
||||||
|
use Vvveb\System\Cache;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Import\Rss;
|
||||||
|
|
||||||
|
class News extends ComponentBase {
|
||||||
|
protected $domain = 'https://blog.vvveb.com';
|
||||||
|
|
||||||
|
protected $url = '/feed/news';
|
||||||
|
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'page' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
function getNews() {
|
||||||
|
$feed = getUrl($this->domain . $this->url, true, 604800, 3, false);
|
||||||
|
|
||||||
|
if ($feed) {
|
||||||
|
$rss = new Rss($feed);
|
||||||
|
|
||||||
|
$result = $rss->get($this->options['page'], $this->options['limit']);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
list($this->domain, $this->url) = Event::trigger(__CLASS__, 'url', $this->domain, $this->url);
|
||||||
|
|
||||||
|
$cache = Cache::getInstance();
|
||||||
|
// check for news ~twice a week
|
||||||
|
$news = $cache->cache('vvveb', 'news', function () {
|
||||||
|
return $this->getNews();
|
||||||
|
}, 259200);
|
||||||
|
|
||||||
|
$results = [
|
||||||
|
'domain' => $this->domain,
|
||||||
|
'url' => $this->url,
|
||||||
|
'news' => $news,
|
||||||
|
'count' => count($news),
|
||||||
|
];
|
||||||
|
|
||||||
|
list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
297
admin/component/notifications.php
Normal file
297
admin/component/notifications.php
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use function Vvveb\commentStatusBadgeClass;
|
||||||
|
use function Vvveb\orderStatusBadgeClass;
|
||||||
|
use Vvveb\Sql\StatSQL;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Update;
|
||||||
|
use function Vvveb\url;
|
||||||
|
|
||||||
|
class Notifications extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
private $stats;
|
||||||
|
|
||||||
|
private $count = 0;
|
||||||
|
|
||||||
|
private $notifications = [];
|
||||||
|
|
||||||
|
private $menu = [];
|
||||||
|
|
||||||
|
protected function orders() {
|
||||||
|
$orderCount = $this->stats->getOrdersCount($this->options)['orders'] ?? [];
|
||||||
|
|
||||||
|
$orderStatsusNew = 1; //get from site config
|
||||||
|
$newOrders = ($orderCount[$orderStatsusNew]['count'] ?? 0);
|
||||||
|
|
||||||
|
if ($newOrders > 0) {
|
||||||
|
$this->count += $newOrders;
|
||||||
|
$this->menu['sales'] = [];
|
||||||
|
$this->menu['sales']['badge'] = $newOrders;
|
||||||
|
$this->menu['sales']['badge-class'] = 'badge bg-success-subtle text-body mx-2';
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = ['module' => 'product/products'];
|
||||||
|
//set order name as array keys
|
||||||
|
foreach ($orderCount as $type => $orders) {
|
||||||
|
if (isset($orders['name'])) {
|
||||||
|
$orders['badge'] = orderStatusBadgeClass($orders['order_status_id']);
|
||||||
|
$orders['icon'] = 'icon-bag-handle-outline';
|
||||||
|
$orders['url'] = url($url + ['filter[order_status_id]' => $orders['order_status_id']]);
|
||||||
|
$orderCount[$orders['name']] = $orders;
|
||||||
|
unset($orderCount[$type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notifications['orders'] = $orderCount + $this->notifications['orders'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function users() {
|
||||||
|
$userCount = $this->stats->getUsersCount($this->options)['users'] ?? [];
|
||||||
|
|
||||||
|
$currentYear = intval(date('Y'));
|
||||||
|
$currentMonth = intval(date('n'));
|
||||||
|
|
||||||
|
$monthCount = 0;
|
||||||
|
$yearCount = 0;
|
||||||
|
|
||||||
|
foreach ($userCount as $m) {
|
||||||
|
if ($m['year'] == $currentYear) {
|
||||||
|
$yearCount += $m['count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($m['year'] == $currentYear && $m['month'] == $currentMonth) {
|
||||||
|
$monthCount += $m['count'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = url(['module' => 'user/users']);
|
||||||
|
|
||||||
|
$this->notifications['users']['month']['count'] = $monthCount;
|
||||||
|
$this->notifications['users']['year']['count'] = $yearCount;
|
||||||
|
$this->notifications['users']['year']['url'] = $url;
|
||||||
|
$this->notifications['users']['month']['url'] = $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function products() {
|
||||||
|
$productCount = $this->stats->getProductStockCount($this->options)['products'] ?? [];
|
||||||
|
$url = ['module' => 'product/products'];
|
||||||
|
|
||||||
|
foreach ($productCount as $type => &$products) {
|
||||||
|
$products['icon'] = 'icon-cube-outline';
|
||||||
|
$products['badge'] = commentStatusBadgeClass($products['stock_status_id']);
|
||||||
|
$products['url'] = url($url + ['filter[stock_status_id]' => $products['stock_status_id']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notifications['products'] = $productCount + $this->notifications['products'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function comments() {
|
||||||
|
$commentCount = $this->stats->getCommentsCount($this->options)['comments'] ?? [];
|
||||||
|
$comment_status = [
|
||||||
|
0 => 'pending',
|
||||||
|
1 => 'approved',
|
||||||
|
2 => 'spam',
|
||||||
|
3 => 'trash',
|
||||||
|
];
|
||||||
|
|
||||||
|
$commentStatsusNew = 0; //get from site config
|
||||||
|
$newComments = ($commentCount[$commentStatsusNew]['count'] ?? 0);
|
||||||
|
|
||||||
|
if ($newComments > 0) {
|
||||||
|
$this->count += $newComments;
|
||||||
|
$this->menu['post'] = [];
|
||||||
|
$this->menu['post']['badge'] = $newComments;
|
||||||
|
$this->menu['post']['badge-class'] = 'badge bg-primary-subtle text-body mx-2';
|
||||||
|
|
||||||
|
$this->menu['post']['items']['comments'] = [];
|
||||||
|
$this->menu['post']['items']['comments']['badge'] = $newComments;
|
||||||
|
$this->menu['post']['items']['comments']['badge-class'] = 'badge bg-primary-subtle text-body mx-2';
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = ['module' => 'content/comments'];
|
||||||
|
|
||||||
|
foreach ($commentCount as $type => $comments) {
|
||||||
|
$comments['icon'] = 'la la-comment';
|
||||||
|
$comments['badge'] = commentStatusBadgeClass($comments['status']);
|
||||||
|
$comments['url'] = url($url + ['status' => $comments['status']]);
|
||||||
|
$commentCount[$comment_status[$type]] = $comments;
|
||||||
|
unset($commentCount[$type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notifications['comments'] = $commentCount + $this->notifications['comments'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function reviews() {
|
||||||
|
$reviewCount = $this->stats->getReviewsCount($this->options)['reviews'] ?? [];
|
||||||
|
$comment_status = [
|
||||||
|
0 => 'pending',
|
||||||
|
1 => 'approved',
|
||||||
|
2 => 'spam',
|
||||||
|
3 => 'trash',
|
||||||
|
];
|
||||||
|
|
||||||
|
$reviewStatsusNew = 0; //get from site config
|
||||||
|
$newReviews = ($reviewCount[$reviewStatsusNew]['count'] ?? 0);
|
||||||
|
|
||||||
|
if ($newReviews > 0) {
|
||||||
|
$this->count += $newReviews;
|
||||||
|
//$this->menu['product'] = [];
|
||||||
|
$this->menu['product']['badge'] = $newReviews;
|
||||||
|
$this->menu['product']['badge-class'] = 'badge bg-primary-subtle text-body mx-2';
|
||||||
|
|
||||||
|
//$this->menu['product']['items']['reviews'] = [];
|
||||||
|
$this->menu['product']['items']['reviews']['badge'] = $newReviews;
|
||||||
|
$this->menu['product']['items']['reviews']['badge-class'] = 'badge bg-primary-subtle text-body mx-2';
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = ['module' => 'product/product-reviews'];
|
||||||
|
|
||||||
|
foreach ($reviewCount as $type => $reviews) {
|
||||||
|
$reviews['icon'] = ' la la-comments';
|
||||||
|
$reviews['badge'] = commentStatusBadgeClass($reviews['status']);
|
||||||
|
$reviews['url'] = url($url + ['status' => $reviews['status']]);
|
||||||
|
$reviewCount[$comment_status[$type]] = $reviews;
|
||||||
|
unset($reviewCount[$type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notifications['reviews'] = $reviewCount + $this->notifications['reviews'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function questions() {
|
||||||
|
$questionCount = $this->stats->getQuestionsCount($this->options)['questions'] ?? [];
|
||||||
|
$comment_status = [
|
||||||
|
0 => 'pending',
|
||||||
|
1 => 'approved',
|
||||||
|
2 => 'spam',
|
||||||
|
3 => 'trash',
|
||||||
|
];
|
||||||
|
|
||||||
|
$questionStatsusNew = 0; //get from site config
|
||||||
|
$newQuestions = ($questionCount[$questionStatsusNew]['count'] ?? 0);
|
||||||
|
|
||||||
|
if ($newQuestions > 0) {
|
||||||
|
$this->count += $newQuestions;
|
||||||
|
//$this->menu['product'] = [];
|
||||||
|
$this->menu['product']['badge'] = ($this->menu['product']['badge'] ?? 0) + $newQuestions;
|
||||||
|
$this->menu['product']['badge-class'] = 'badge bg-primary-subtle text-body mx-2';
|
||||||
|
|
||||||
|
//$this->menu['product']['items']['questions'] = [];
|
||||||
|
$this->menu['product']['items']['questions']['badge'] = $newQuestions;
|
||||||
|
$this->menu['product']['items']['questions']['badge-class'] = 'badge bg-primary-subtle text-body mx-2';
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = ['module' => 'product/product-questions'];
|
||||||
|
|
||||||
|
foreach ($questionCount as $type => $questions) {
|
||||||
|
$questions['icon'] = 'la la-question-circle';
|
||||||
|
$questions['badge'] = commentStatusBadgeClass($questions['status']);
|
||||||
|
$questions['url'] = url($url + ['status' => $questions['status']]);
|
||||||
|
$questionCount[$comment_status[$type]] = $questions;
|
||||||
|
unset($questionCount[$type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notifications['questions'] = $questionCount + $this->notifications['questions'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function request(&$results, $index) {
|
||||||
|
//add menu notification count
|
||||||
|
|
||||||
|
if ($results['menu'] && $index == 0) {
|
||||||
|
$view = View::getInstance();
|
||||||
|
|
||||||
|
if (isset($view->menu) && $view->menu) {
|
||||||
|
$view->menu = array_replace_recursive($view->menu, $results['menu']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
// return [];
|
||||||
|
$this->notifications = [
|
||||||
|
'updates' => [
|
||||||
|
'core' => ['hasUpdate' => 0, 'version' => V_VERSION],
|
||||||
|
],
|
||||||
|
'orders' => [
|
||||||
|
'processing' => ['count' => 0, 'icon' => 'icon-bag-handle-outline', 'badge' => 'bg-primary-subtle text-body'],
|
||||||
|
'complete' => ['count' => 0, 'icon' => 'icon-bag-handle-outline', 'badge' => 'bg-success-subtle text-body'],
|
||||||
|
'processed' => ['count' => 0, 'icon' => 'icon-bag-handle-outline', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
],
|
||||||
|
'users' => [
|
||||||
|
'month' => ['count' => 0, 'icon' => 'icon-person-outline', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
'year' => ['count' => 0, 'icon' => 'icon-person-outline', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
],
|
||||||
|
'products' => [
|
||||||
|
],
|
||||||
|
'comments' => [
|
||||||
|
'pending' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-primary-subtle text-body'],
|
||||||
|
'approved' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
'spam' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
'trash' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
],
|
||||||
|
'reviews' => [
|
||||||
|
'pending' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-primary-subtle text-body'],
|
||||||
|
'approved' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
'spam' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
'trash' => ['count' => 0, 'icon' => 'la la-comment', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
],
|
||||||
|
'questions' => [
|
||||||
|
'pending' => ['count' => 0, 'icon' => 'la la-question-circle', 'badge' => 'bg-primary-subtle text-body'],
|
||||||
|
'approved' => ['count' => 0, 'icon' => 'la la-question-circle', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
'spam' => ['count' => 0, 'icon' => 'la la-question-circle', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
'trash' => ['count' => 0, 'icon' => 'la la-question-circle', 'badge' => 'bg-secondary-subtle text-body'],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->stats = new StatSQL();
|
||||||
|
$this->orders();
|
||||||
|
$this->users();
|
||||||
|
$this->products();
|
||||||
|
$this->comments();
|
||||||
|
$this->reviews();
|
||||||
|
$this->questions();
|
||||||
|
|
||||||
|
$update = new Update();
|
||||||
|
//$updates = $update->checkUpdates('core') ?? [];
|
||||||
|
|
||||||
|
//$this->notifications['updates']['core'] = $updates;
|
||||||
|
$this->count += max($updates['hasUpdate'] ?? 0, 0);
|
||||||
|
|
||||||
|
$results = [
|
||||||
|
'notifications' => $this->notifications,
|
||||||
|
'count' => $this->count,
|
||||||
|
'menu' => $this->menu,
|
||||||
|
];
|
||||||
|
|
||||||
|
list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
admin/component/order.php
Normal file
23
admin/component/order.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
include DIR_ROOT . 'app' . DS . 'component' . DS . 'order.php';
|
||||||
88
admin/component/orders.php
Normal file
88
admin/component/orders.php
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use Vvveb\System\Cart\Currency;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Orders extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'language_id' => NULL,
|
||||||
|
'site_id' => NULL,
|
||||||
|
'user_id' => NULL,
|
||||||
|
'email' => NULL,
|
||||||
|
'phone_number' => NULL,
|
||||||
|
'search' => NULL,
|
||||||
|
'id_manufacturer' => NULL,
|
||||||
|
'order_status' => NULL,
|
||||||
|
'order_status_id' => NULL,
|
||||||
|
'order_by' => NULL,
|
||||||
|
'direction' => ['url', 'asc', 'desc'],
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$orders = new \Vvveb\Sql\OrderSQL();
|
||||||
|
|
||||||
|
$results = $orders->getAll($this->options);
|
||||||
|
|
||||||
|
if (isset($this->options['order_by']) &&
|
||||||
|
! in_array($this->options['order_by'], ['order_id', 'customer_order_id', 'order_status_id', 'created_at'])) {
|
||||||
|
unset($this->options['order_by']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->options['direction']) &&
|
||||||
|
! in_array($this->options['direction'], ['asc', 'desc'])) {
|
||||||
|
unset($this->options['direction']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($results['order']) {
|
||||||
|
$currency = Currency::getInstance();
|
||||||
|
|
||||||
|
foreach ($results['order'] as $id => &$order) {
|
||||||
|
if (isset($order['images'])) {
|
||||||
|
$order['images'] = json_decode($order['images'], 1);
|
||||||
|
|
||||||
|
foreach ($order['images'] as &$image) {
|
||||||
|
$image = Images::image('order', $image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($order['image'])) {
|
||||||
|
$order['images'][] = Images::image('order', $order['image']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$order['total_formatted'] = $currency->format($order['total']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
admin/component/posts.php
Normal file
68
admin/component/posts.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use Vvveb\Sql\PostSQL;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Posts extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 0,
|
||||||
|
'language_id' => 1,
|
||||||
|
'site_id' => 1,
|
||||||
|
'post_id' => 'url',
|
||||||
|
'limit' => ['url', 4],
|
||||||
|
'id_manufacturer' => NULL,
|
||||||
|
'order' => ['url', 'price asc'],
|
||||||
|
'id_category' => 'url',
|
||||||
|
'id' => NULL,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$posts = new PostSQL();
|
||||||
|
|
||||||
|
$results = $posts->getAll($this->options);
|
||||||
|
|
||||||
|
foreach ($results['post'] as $id => &$post) {
|
||||||
|
if (isset($post['images'])) {
|
||||||
|
$post['images'] = json_decode($post['images'], 1);
|
||||||
|
|
||||||
|
foreach ($post['images'] as &$image) {
|
||||||
|
$image = Images::image($image, 'post');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($post['image'])) {
|
||||||
|
$post['images'][] = Images::image($post['image'], 'post');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
admin/component/product.php
Normal file
25
admin/component/product.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
include DIR_ROOT . 'app' . DS . 'component' . DS . 'product.php';
|
||||||
85
admin/component/products.php
Normal file
85
admin/component/products.php
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use Vvveb\System\Cart\Currency;
|
||||||
|
use Vvveb\System\Cart\Tax;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Products extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 4,
|
||||||
|
'language_id' => 1,
|
||||||
|
'site_id' => 1,
|
||||||
|
'manufacturer_id'=> NULL,
|
||||||
|
'vendor_id' => NULL,
|
||||||
|
'related' => NULL,
|
||||||
|
'order' => ['url', 'price asc'],
|
||||||
|
//'taxonomy_item_id'=> null,
|
||||||
|
'product_image' => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
function __construct($class = __CLASS__) {
|
||||||
|
parent::__construct($class);
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$products = new \Vvveb\Sql\ProductSQL();
|
||||||
|
|
||||||
|
$results = $products->getAll($this->options);
|
||||||
|
|
||||||
|
$results['product'] = $results['product'] ?? [];
|
||||||
|
|
||||||
|
if ($results['product']) {
|
||||||
|
$tax = Tax::getInstance($this->options);
|
||||||
|
$currency = Currency::getInstance($this->options);
|
||||||
|
|
||||||
|
foreach ($results['product'] as $id => &$product) {
|
||||||
|
if (isset($product['images'])) {
|
||||||
|
$product['images'] = json_decode($product['images'], true);
|
||||||
|
|
||||||
|
foreach ($product['images'] as &$image) {
|
||||||
|
$image['image'] = Images::image($image['image'], 'product');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($product['image']) && $product['image']) {
|
||||||
|
$product['image'] =Images::image($product['image'], 'product');
|
||||||
|
}
|
||||||
|
|
||||||
|
$product['price_tax'] = $tax->addTaxes($product['price'], $product['tax_type_id']);
|
||||||
|
$product['price_tax_formatted'] = $currency->format($product['price_tax']);
|
||||||
|
$product['price_formatted'] = $currency->format($product['price']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event :: trigger(__CLASS__,__FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
admin/component/site.php
Normal file
23
admin/component/site.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
include DIR_ROOT . 'app' . DS . 'component' . DS . 'site.php';
|
||||||
72
admin/component/sites.php
Normal file
72
admin/component/sites.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use function Vvveb\session as sess;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Sites as SitesList;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
|
||||||
|
class Sites extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'limit' => 1000,
|
||||||
|
'page' => 1,
|
||||||
|
'site_access' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $options = [];
|
||||||
|
|
||||||
|
public $cacheExpire = 0; //seconds
|
||||||
|
|
||||||
|
function cacheKey() {
|
||||||
|
//disable caching
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
$results['sites'] = SitesList::getSites();
|
||||||
|
$results['states'] = SitesList::getStates();
|
||||||
|
$results['site_id'] = sess('site_id');
|
||||||
|
$results['active'] = SitesList::getSiteById($results['site_id']);
|
||||||
|
$results['count'] = count($results['sites']);
|
||||||
|
|
||||||
|
if ($this->options['site_access']) {
|
||||||
|
$site_access = Admin::siteAccess();
|
||||||
|
|
||||||
|
if ($site_access) {
|
||||||
|
foreach ($results['sites'] as $key => $site) {
|
||||||
|
if (! in_array($site['id'], $site_access)) {
|
||||||
|
unset($results['sites'][$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event :: trigger(__CLASS__,__FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
56
admin/component/states.php
Normal file
56
admin/component/states.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use function Vvveb\session as sess;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
|
||||||
|
class States extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $options = [];
|
||||||
|
|
||||||
|
public $cacheExpire = 0; //seconds
|
||||||
|
|
||||||
|
function cacheKey() {
|
||||||
|
//disable caching
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$states = Sites::getStates();
|
||||||
|
$active = sess('state') ?? 'live';
|
||||||
|
$results['active_name'] = $states[$active]['name'];
|
||||||
|
$results['active_icon'] = $states[$active]['icon'];
|
||||||
|
|
||||||
|
$results['states'] = $states;
|
||||||
|
$results['active'] = $active;
|
||||||
|
|
||||||
|
list($results) = Event :: trigger(__CLASS__,__FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
82
admin/component/stats.php
Normal file
82
admin/component/stats.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use Vvveb\Sql\StatSQL;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
|
||||||
|
class Stats extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'language_id' => null,
|
||||||
|
'site_id' => null,
|
||||||
|
'stat' => ['url', 'price asc'],
|
||||||
|
'start_date' => '',
|
||||||
|
'end_date' => 'NOW()',
|
||||||
|
'range' => 'day', //day, week, month, year
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$stats = new StatSQL();
|
||||||
|
|
||||||
|
if ($this->options['end_date'] == 'NOW()') {
|
||||||
|
$this->options['end_date'] = date('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->options['start_date'] == 'NOW()') {
|
||||||
|
$this->options['start_date'] = date('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = $stats->getStats($this->options);
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($results['orders'] as $order) {
|
||||||
|
$data[$order['date']]['orders'] = $order['orders'];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($results['users'] as $order) {
|
||||||
|
$data[$order['date']]['users'] = $order['users'];
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($data);
|
||||||
|
$labels = array_keys($data);
|
||||||
|
|
||||||
|
$users = [];
|
||||||
|
$orders = [];
|
||||||
|
|
||||||
|
foreach ($data as $date => $stat) {
|
||||||
|
$users[] = $stat['users'] ?? 0;
|
||||||
|
$orders[] = $stat['orders'] ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($labels, $users, $orders) = Event :: trigger(__CLASS__,__FUNCTION__, $labels, $users, $orders);
|
||||||
|
|
||||||
|
return ['labels' => $labels, 'users' => $users, 'orders' => $orders];
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
admin/component/user/address.php
Normal file
23
admin/component/user/address.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
include DIR_ROOT . 'app' . DS . 'component' . DS . 'user' . DS . 'address.php';
|
||||||
64
admin/component/user/wishlist.php
Normal file
64
admin/component/user/wishlist.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component\User;
|
||||||
|
|
||||||
|
use Vvveb\Sql\User_WishlistSQL;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use function Vvveb\url;
|
||||||
|
|
||||||
|
class Wishlist extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
];
|
||||||
|
|
||||||
|
//don't cache
|
||||||
|
function cacheKey() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
if ($this->options['user_id']) {
|
||||||
|
$wishlist = new User_WishlistSQL();
|
||||||
|
$results = $wishlist->getAll($this->options);
|
||||||
|
|
||||||
|
if ($results && isset($results['wishlist'])) {
|
||||||
|
foreach ($results['wishlist'] as $id => &$wishlist) {
|
||||||
|
$wishlist['url'] = url('user/wishlist/edit', $wishlist);
|
||||||
|
$wishlist['delete-url'] = url('user/wishlist/delete', $wishlist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event :: trigger(__CLASS__,__FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
//called on each request
|
||||||
|
function request($results, $index = 0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
78
admin/component/users.php
Normal file
78
admin/component/users.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Component;
|
||||||
|
|
||||||
|
use Vvveb\Sql\UserSQL;
|
||||||
|
use Vvveb\System\Component\ComponentBase;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Users extends ComponentBase {
|
||||||
|
public static $defaultOptions = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'site_id' => null,
|
||||||
|
'user_id' => 'url',
|
||||||
|
'user' => ['url', 'price asc'],
|
||||||
|
'order_by' => NULL,
|
||||||
|
'direction' => ['url', 'asc', 'desc'],
|
||||||
|
];
|
||||||
|
|
||||||
|
public $options = [];
|
||||||
|
|
||||||
|
function results() {
|
||||||
|
$users = new UserSQL();
|
||||||
|
|
||||||
|
$results = $users->getAll($this->options);
|
||||||
|
|
||||||
|
if (isset($this->options['order_by']) &&
|
||||||
|
! in_array($this->options['order_by'], ['user_id', 'created_at', 'email', 'username'])) {
|
||||||
|
unset($this->options['order_by']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->options['direction']) &&
|
||||||
|
! in_array($this->options['direction'], ['asc', 'desc'])) {
|
||||||
|
unset($this->options['direction']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($results['user'])) {
|
||||||
|
foreach ($results['user'] as $id => &$user) {
|
||||||
|
if (isset($user['images'])) {
|
||||||
|
$user['images'] = json_decode($user['images'], 1);
|
||||||
|
|
||||||
|
foreach ($user['images'] as &$image) {
|
||||||
|
$image = Images::image('user', $image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($user['image'])) {
|
||||||
|
$user['images'][] = Images::image($user['image'], 'user');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($results) = Event :: trigger(__CLASS__,__FUNCTION__, $results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
84
admin/controller/admin/auth-token.php
Normal file
84
admin/controller/admin/auth-token.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Admin;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use Vvveb\Sql\Admin_Auth_TokenSQL;
|
||||||
|
use function Vvveb\url;
|
||||||
|
///use Vvveb\System\Traits\Crud as CrudTrait;
|
||||||
|
|
||||||
|
class AuthToken extends Listing {
|
||||||
|
/*
|
||||||
|
use CrudTrait {
|
||||||
|
CrudTrait::delete as get;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
protected $type = 'admin_auth_token';
|
||||||
|
|
||||||
|
protected $list = 'admin_auth_token';
|
||||||
|
|
||||||
|
protected $listController = 'auth_token';
|
||||||
|
|
||||||
|
protected $module = 'admin';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$this->options['admin_id'] = $this->request->get['admin_id'] ?? false;
|
||||||
|
$this->options['limit'] =1000;
|
||||||
|
|
||||||
|
if (! $this->options['admin_id']) {
|
||||||
|
return $this->notFound(true, __('User not found!'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->user_url = url(['module' => 'admin/user', 'admin_id' => $this->options['admin_id']]);
|
||||||
|
parent::index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$admin_auth_token = $this->request->post['admin_auth_token'] ?? [];
|
||||||
|
$admin_id = $this->request->get['admin_id'] ?? false;
|
||||||
|
|
||||||
|
if ($admin_auth_token && $admin_id) {
|
||||||
|
foreach ($admin_auth_token as $key => $token) {
|
||||||
|
if ($key == '#') {
|
||||||
|
unset($admin_auth_token[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $token['admin_auth_token_id']) {
|
||||||
|
unset($admin_auth_token[$key]['admin_auth_token_id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$adminAuthToken = new Admin_Auth_TokenSQL();
|
||||||
|
|
||||||
|
if (($result = $adminAuthToken->update(['admin_auth_token' => $admin_auth_token, 'admin_id' => $admin_id] + $this->global))/* && $result['admin_auth_token']*/) {
|
||||||
|
$this->view->success['get'] =humanReadable(__($this->type)) . __(' saved!');
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index();
|
||||||
|
}
|
||||||
|
}
|
||||||
141
admin/controller/admin/role.php
Normal file
141
admin/controller/admin/role.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Admin;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use Vvveb\Sql\RoleSQL;
|
||||||
|
use Vvveb\System\Cache;
|
||||||
|
use Vvveb\System\User\Role as RoleList;
|
||||||
|
|
||||||
|
class Role extends Base {
|
||||||
|
protected $type = 'role';
|
||||||
|
|
||||||
|
protected $app = 'admin';
|
||||||
|
|
||||||
|
protected $apps = [
|
||||||
|
'admin' => ['permissions' => ['controllers']],
|
||||||
|
'rest' => ['permissions' => ['routes', 'controllers']],
|
||||||
|
'graphql' => ['permissions' => ['controllers', 'models']],
|
||||||
|
];
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
$this->app = $this->request->get['app'] ?? 'admin';
|
||||||
|
|
||||||
|
if (! isset($this->apps[$this->app])) {
|
||||||
|
//$this->view->errors[] = __('Invalid app!');
|
||||||
|
return $this->notFound(__('Invalid app!'));
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$role_id = $this->request->get['role_id'] ?? false;
|
||||||
|
|
||||||
|
$cache = Cache::getInstance();
|
||||||
|
$tree = $cache->cache(APP, $this->app . '-permissions',function () {
|
||||||
|
$tree = [];
|
||||||
|
//$this->view->tree = RoleList::controllers($this->app);
|
||||||
|
foreach ($this->apps[$this->app]['permissions'] as $method) {
|
||||||
|
$data = RoleList::$method($this->app);
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
$tree += RoleList::$method($this->app);
|
||||||
|
}
|
||||||
|
////$this->view->tree = $tree['controller'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tree;
|
||||||
|
}, 259200);
|
||||||
|
|
||||||
|
$this->view->tree = $tree;
|
||||||
|
|
||||||
|
//\Vvveb\dd($this->view->tree);
|
||||||
|
|
||||||
|
//$this->view->controllers = RoleList::getControllerList($this->app);
|
||||||
|
$this->view->capabilities = RoleList::getCapabilitiesList($this->app);
|
||||||
|
$this->view->apps = $this->apps;
|
||||||
|
$this->view->app = $this->app;
|
||||||
|
|
||||||
|
$role = new RoleSQL();
|
||||||
|
$this->view->role = $role->get(['role_id' => $role_id]);
|
||||||
|
|
||||||
|
if ($this->view->role) {
|
||||||
|
$permissions = json_decode($this->view->role['permissions'], true);
|
||||||
|
|
||||||
|
if (isset($permissions[$this->app])) {
|
||||||
|
$permissions = $permissions[$this->app];
|
||||||
|
} else {
|
||||||
|
//backward compatibility for admin app
|
||||||
|
if ($this->app !== 'admin') {
|
||||||
|
$permissions = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->role['permissions'] = $permissions;
|
||||||
|
$this->view->role['permissions']['deny'] = $this->view->role['permissions']['deny'] ?? [];
|
||||||
|
$this->view->role['permissions']['allow'] = $this->view->role['permissions']['allow'] ?? [];
|
||||||
|
$this->view->role['permissions']['capabilities'] = $this->view->role['permissions']['capabilities'] ?? [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$data = $this->request->post['role'] ?? [];
|
||||||
|
$allow = $this->request->post['allow'] ?? [];
|
||||||
|
$deny = $this->request->post['deny'] ?? [];
|
||||||
|
$capabilities = $this->request->post['capabilities'] ?? [];
|
||||||
|
$permissions = [$this->app => ['deny' => $deny, 'allow' => $allow, 'capabilities' => $capabilities]];
|
||||||
|
|
||||||
|
$role_id = $this->request->get['role_id'] ?? false;
|
||||||
|
|
||||||
|
$role = new RoleSQL();
|
||||||
|
$this->view->role = $role->get(['role_id' => $role_id]);
|
||||||
|
$currentPermissions = json_decode($this->view->role['permissions'], true);
|
||||||
|
|
||||||
|
if ($currentPermissions) {
|
||||||
|
//backward compatibility
|
||||||
|
if (isset($currentPermissions['allow'])) {
|
||||||
|
$currentPermissions['admin'] = $currentPermissions;
|
||||||
|
unset($currentPermissions['allow'], $currentPermissions['deny'], $currentPermissions['capabilities']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentPermissions[$this->app] = $permissions[$this->app];
|
||||||
|
$permissions = $currentPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($role_id) {
|
||||||
|
$result = $role->edit(['role_id' => $role_id, 'role' => $data + ['permissions' => json_encode($permissions)]]);
|
||||||
|
} else {
|
||||||
|
$result = $role->add(['role' => $data + ['permissions' => json_encode($permissions)]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result && isset($result['role'])) {
|
||||||
|
$this->view->success[] = __('Saved!');
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
}
|
||||||
37
admin/controller/admin/roles.php
Normal file
37
admin/controller/admin/roles.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Admin;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Roles extends Listing {
|
||||||
|
protected $type = 'role';
|
||||||
|
|
||||||
|
protected $controller = 'role';
|
||||||
|
|
||||||
|
protected $listController = 'roles';
|
||||||
|
|
||||||
|
protected $list = 'role';
|
||||||
|
|
||||||
|
protected $module = 'admin';
|
||||||
|
}
|
||||||
53
admin/controller/admin/user.php
Normal file
53
admin/controller/admin/user.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Admin;
|
||||||
|
|
||||||
|
use Vvveb\Controller\User\User as UserBase;
|
||||||
|
use Vvveb\Sql\SiteSQL;
|
||||||
|
|
||||||
|
class User extends UserBase {
|
||||||
|
protected $type = 'admin';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent :: index();
|
||||||
|
|
||||||
|
$roles = new \Vvveb\Sql\RoleSQL();
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'type' => 'admin', //$this->type,
|
||||||
|
'limit'=> 100,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$roles = $roles->getAll($options);
|
||||||
|
$sites = new SiteSQL();
|
||||||
|
|
||||||
|
if (!isset($this->view->user['site_access'])) {
|
||||||
|
//set default site access to current site for new user
|
||||||
|
$this->view->user['site_access'] = [$this->global['site_id']];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->admin_auth_token_url = \Vvveb\url(['module' => 'admin/auth-token', 'admin_id' => $this->request->get['admin_id'] ?? '']);
|
||||||
|
$this->view->sitesList = $sites->getAll()['site'] ?? [];
|
||||||
|
$this->view->roles = array_reverse($roles ? $roles['role'] : []);
|
||||||
|
}
|
||||||
|
}
|
||||||
42
admin/controller/admin/users.php
Normal file
42
admin/controller/admin/users.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Admin;
|
||||||
|
|
||||||
|
use Vvveb\Controller\User\Users as UsersBase;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
|
||||||
|
class Users extends UsersBase {
|
||||||
|
protected $type = 'admin';
|
||||||
|
|
||||||
|
protected $module = 'admin/users';
|
||||||
|
|
||||||
|
function index($options = []) {
|
||||||
|
if (Admin::hasCapability('view_other_admin')) {
|
||||||
|
unset($options['admin_id']);
|
||||||
|
} else {
|
||||||
|
$options['admin_id'][] = $this->global['admin_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::index($options);
|
||||||
|
}
|
||||||
|
}
|
||||||
640
admin/controller/base.php
Normal file
640
admin/controller/base.php
Normal file
@ -0,0 +1,640 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use function Vvveb\arrayInsertArrayAfter;
|
||||||
|
use function Vvveb\availableCurrencies;
|
||||||
|
use function Vvveb\availableLanguages;
|
||||||
|
use function Vvveb\clearLanguageCache;
|
||||||
|
use function Vvveb\filter;
|
||||||
|
use function Vvveb\setLanguage;
|
||||||
|
use Vvveb\Sql\taxonomySQL;
|
||||||
|
use Vvveb\System\Cache;
|
||||||
|
use Vvveb\System\Core\FrontController;
|
||||||
|
use Vvveb\System\Core\Request;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Extensions\Plugins;
|
||||||
|
use Vvveb\System\Functions\Str;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
use Vvveb\System\PageCache;
|
||||||
|
use Vvveb\System\Session;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
use Vvveb\System\Traits\Permission;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
|
||||||
|
#[\AllowDynamicProperties]
|
||||||
|
class Base {
|
||||||
|
use Permission;
|
||||||
|
|
||||||
|
public $view;
|
||||||
|
|
||||||
|
public $request;
|
||||||
|
|
||||||
|
public $sesssion;
|
||||||
|
|
||||||
|
protected $global;
|
||||||
|
|
||||||
|
protected function setSite($site_id = false) {
|
||||||
|
//if no id set default
|
||||||
|
if ($site_id) {
|
||||||
|
$site = Sites::getSiteById($site_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $site_id || ! $site) {
|
||||||
|
$site = Sites::getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
$site_id = $site['id'];
|
||||||
|
$this->session->set('site', $site);
|
||||||
|
$this->session->set('site_id', $site_id);
|
||||||
|
$this->session->set('site_url', $site['url']);
|
||||||
|
$this->session->set('site', $site['id']);
|
||||||
|
$this->session->set('host', $site['host']);
|
||||||
|
$this->session->set('state', $site['state'] ?? 'live');
|
||||||
|
|
||||||
|
return $site_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTaxonomies() {
|
||||||
|
$categories = new taxonomySQL();
|
||||||
|
$taxonomies = $categories->getAll($this->global);
|
||||||
|
|
||||||
|
return $taxonomies['taxonomy'] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function customPost() {
|
||||||
|
//custom posts -- add to menu
|
||||||
|
$default_custom_posts =
|
||||||
|
[
|
||||||
|
'post' => [
|
||||||
|
'type' => 'post',
|
||||||
|
'plural' => 'posts',
|
||||||
|
'icon' => 'icon-document-text-outline',
|
||||||
|
'comments'=> true,
|
||||||
|
],
|
||||||
|
'page' => [
|
||||||
|
'type' => 'page',
|
||||||
|
'plural' => 'pages',
|
||||||
|
'icon' => 'icon-document-outline',
|
||||||
|
'comments'=> false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$custom_posts_types = \Vvveb\getSetting('post', 'types', []);
|
||||||
|
$custom_posts_types += $default_custom_posts;
|
||||||
|
list($custom_posts_types) = Event::trigger('Vvveb\postTypes', __FUNCTION__, $custom_posts_types);
|
||||||
|
|
||||||
|
$custom_post_menu = \Vvveb\config('custom-post-menu', []);
|
||||||
|
$posts_menu = [];
|
||||||
|
|
||||||
|
foreach ($custom_posts_types as $type => $settings) {
|
||||||
|
if ($type == 'page') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$posts_menu[$type] = $custom_post_menu;
|
||||||
|
|
||||||
|
$posts_menu[$type]['name'] =
|
||||||
|
$posts_menu[$type]['items']['posts']['name'] =
|
||||||
|
__(ucfirst($settings['plural']));
|
||||||
|
|
||||||
|
$posts_menu[$type]['icon'] = $settings['icon'] ?? '';
|
||||||
|
$posts_menu[$type]['icon-img'] = (isset($settings['icon-img']) && $settings['icon-img']) ? Images::image($settings['icon-img'], $type) : '';
|
||||||
|
$posts_menu[$type]['url'] .= "&type=$type";
|
||||||
|
|
||||||
|
if (isset($settings['comments']) && ! $settings['comments']) {
|
||||||
|
unset($posts_menu[$type]['items']['comments']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($posts_menu[$type]['items'] as $item => &$values) {
|
||||||
|
if (isset($values['url'])) {
|
||||||
|
$values['url'] .= "&type=$type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
//add taxonomies for post type
|
||||||
|
foreach ($this->taxonomies as $taxonomy) {
|
||||||
|
if ($taxonomy['post_type'] != $type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$key = $taxonomy['post_type'] . '_' . $taxonomy['type'] . $taxonomy['taxonomy_id'];
|
||||||
|
$module = "content/{$taxonomy['type']}";
|
||||||
|
$icon = $taxonomy['type'] == 'tags' ? 'la la-tags' : 'la la-boxes';
|
||||||
|
$tax = [$key => [
|
||||||
|
'name' => __($taxonomy['name']),
|
||||||
|
//'subtitle' => __('(Flat)'),
|
||||||
|
'url' => "{$admin_path}index.php?module=$module&type={$taxonomy['post_type']}&taxonomy_id={$taxonomy['taxonomy_id']}",
|
||||||
|
'module' => $module,
|
||||||
|
'action' => 'index',
|
||||||
|
'icon' => $icon,
|
||||||
|
]];
|
||||||
|
|
||||||
|
$posts_menu[$type]['items'] = arrayInsertArrayAfter('taxonomy-heading', $posts_menu[$type]['items'], $tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $posts_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function customProduct() {
|
||||||
|
//custom products -- add to menu
|
||||||
|
$default_custom_products =
|
||||||
|
[
|
||||||
|
'product' => [
|
||||||
|
'type' => 'product',
|
||||||
|
'plural' => 'products',
|
||||||
|
'icon' => 'icon-cube-outline',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$custom_products_types = \Vvveb\getSetting('product', 'types', []);
|
||||||
|
$custom_products_types += $default_custom_products;
|
||||||
|
list($custom_products_types) = Event::trigger('Vvveb\postTypes', __FUNCTION__, $custom_products_types);
|
||||||
|
|
||||||
|
$custom_product_menu = \Vvveb\config('custom-product-menu', []);
|
||||||
|
$products_menu = [];
|
||||||
|
|
||||||
|
foreach ($custom_products_types as $type => $settings) {
|
||||||
|
if ($type == 'page') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$products_menu[$type] = $custom_product_menu;
|
||||||
|
|
||||||
|
$products_menu[$type]['name'] =
|
||||||
|
$products_menu[$type]['items']['products']['name'] =
|
||||||
|
__(ucfirst($settings['plural']));
|
||||||
|
|
||||||
|
$products_menu[$type]['icon'] = $settings['icon'] ?? '';
|
||||||
|
$products_menu[$type]['icon-img'] = (isset($settings['icon-img']) && $settings['icon-img']) ? Images::image($settings['icon-img'], $type) : '';
|
||||||
|
$products_menu[$type]['url'] .= "&type=$type";
|
||||||
|
|
||||||
|
foreach ($products_menu[$type]['items'] as $item => &$values) {
|
||||||
|
if (isset($values['url'])) {
|
||||||
|
$values['url'] .= "&type=$type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
//add taxonomies for post type
|
||||||
|
foreach ($this->taxonomies as $taxonomy) {
|
||||||
|
if ($taxonomy['post_type'] != $type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$key = $taxonomy['post_type'] . '_' . $taxonomy['type'] . $taxonomy['taxonomy_id'];
|
||||||
|
|
||||||
|
$module = "content/{$taxonomy['type']}";
|
||||||
|
$icon = $taxonomy['type'] == 'tags' ? 'la la-tags' : 'la la-boxes';
|
||||||
|
$tax = [$key => [
|
||||||
|
'name' => __($taxonomy['name']),
|
||||||
|
//'subtitle' => __('(Flat)'),
|
||||||
|
'url' => "{$admin_path}index.php?module=$module&type={$taxonomy['post_type']}&taxonomy_id={$taxonomy['taxonomy_id']}",
|
||||||
|
'module' => $module,
|
||||||
|
'action' => 'index',
|
||||||
|
'icon' => $icon,
|
||||||
|
]];
|
||||||
|
|
||||||
|
$products_menu[$type]['items'] = arrayInsertArrayAfter('taxonomy-heading', $products_menu[$type]['items'], $tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $products_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function language($defaultLanguage = false, $defaultLanguageId = false, $defaultLocale = false) {
|
||||||
|
$languages = availableLanguages();
|
||||||
|
|
||||||
|
$default_language = $this->session->get('default_language');
|
||||||
|
$default_language_id = $this->session->get('default_language_id');
|
||||||
|
$default_locale = $this->session->get('default_locale');
|
||||||
|
$site_language = false;
|
||||||
|
|
||||||
|
if (($lang = ($this->request->post['language'] ?? false)) && ! is_array($lang)) {
|
||||||
|
$language = filter('/[A-Za-z_-]+/', $lang, 10);
|
||||||
|
|
||||||
|
if (isset($languages[$language])) {
|
||||||
|
$this->session->set('language', $language);
|
||||||
|
$this->session->set('language_id', $languages[$language]['language_id']);
|
||||||
|
$this->session->set('locale', $languages[$language]['locale']);
|
||||||
|
$this->session->set('rtl', $languages[$language]['rtl'] ?? false);
|
||||||
|
$default_language = false; //recheck default language
|
||||||
|
clearLanguageCache($language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $default_language) {
|
||||||
|
foreach ($languages as $code => $lang) {
|
||||||
|
//set site language
|
||||||
|
if ($defaultLanguageId && ($defaultLanguageId == $lang['language_id'])) {
|
||||||
|
$site_language = $code;
|
||||||
|
$site_language_id = $lang['language_id'];
|
||||||
|
$site_locale = $lang['locale'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//set global default language
|
||||||
|
if ($lang['default']) {
|
||||||
|
$default_language = $code;
|
||||||
|
$default_language_id = $lang['language_id'];
|
||||||
|
$default_locale = $lang['locale'];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($site_language) {
|
||||||
|
$default_language = $site_language;
|
||||||
|
$default_language_id = $site_language_id;
|
||||||
|
$default_locale = $site_locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
//no valid default site or global language? set english as default
|
||||||
|
if (! $default_language) {
|
||||||
|
$default_language = 'en_US';
|
||||||
|
$default_language_id = 1;
|
||||||
|
$default_locale = 'en-us';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->session->set('default_language', $default_language);
|
||||||
|
$this->session->set('default_language_id', $default_language_id);
|
||||||
|
$this->session->set('default_locale', $default_locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
$language = $this->session->get('language') ?? $default_language;
|
||||||
|
$language_id = $this->session->get('language_id') ?? $default_language_id;
|
||||||
|
$locale = $this->session->get('locale') ?? $default_locale;
|
||||||
|
$rtl = $this->session->get('rtl') ?? false;
|
||||||
|
|
||||||
|
//if no default language configured then set first language as current language
|
||||||
|
if (! isset($languages[$language])) {
|
||||||
|
$default_language = key($languages);
|
||||||
|
$lang = $languages[$default_language] ?? [];
|
||||||
|
|
||||||
|
if ($lang) {
|
||||||
|
$default_language_id = $lang['language_id'] ?? $defaultLanguageId;
|
||||||
|
$default_locale = $lang['locale'] ?? $defaultLocale;
|
||||||
|
$default_rtl = $lang['rtl'] ?? false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if no language configured then set default language as current language
|
||||||
|
if (! $language) {
|
||||||
|
$language = $default_language;
|
||||||
|
$language_id = $default_language_id;
|
||||||
|
$locale = $default_locale;
|
||||||
|
$rtl = $default_rtl;
|
||||||
|
$this->session->set('language', $language);
|
||||||
|
$this->session->set('language_id', $language_id);
|
||||||
|
$this->session->set('locale', $locale);
|
||||||
|
$this->session->set('rtl', $rtl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->global['language'] = $language;
|
||||||
|
$this->global['locale'] = $locale;
|
||||||
|
$this->global['language_id'] = $language_id;
|
||||||
|
$this->global['rtl'] = $rtl;
|
||||||
|
$this->global['default_language'] = $default_language;
|
||||||
|
$this->global['default_locale'] = $default_locale;
|
||||||
|
$this->global['default_language_id'] = $default_language_id;
|
||||||
|
|
||||||
|
setLanguage($language);
|
||||||
|
|
||||||
|
if (! defined('CLI')) {
|
||||||
|
$view = $this->view;
|
||||||
|
$view->languagesList = $languages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function currency($defaultCurrency = false, $defaultCurrencyId = false) {
|
||||||
|
if (($currency = ($this->request->post['currency'] ?? false)) && ! is_array($currency)) {
|
||||||
|
$currency = filter('/[A-Za-z_-]+/', $currency, 50);
|
||||||
|
$currencies = availableCurrencies();
|
||||||
|
|
||||||
|
if (isset($currencies[$currency])) {
|
||||||
|
$this->session->set('currency_id', $currencies[$currency]['currency_id']);
|
||||||
|
$this->session->set('currency', $currency);
|
||||||
|
|
||||||
|
\Vvveb\System\Cart\Cart::getInstance($this->global)->updateCart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$currency = $this->session->get('currency');
|
||||||
|
$currency_id = $this->session->get('currency_id');
|
||||||
|
|
||||||
|
if (! $currency || ! $currency_id) {
|
||||||
|
$currencies = availableCurrencies();
|
||||||
|
|
||||||
|
if ($currencies) {
|
||||||
|
foreach ($currencies as $code => $c) {
|
||||||
|
if ($defaultCurrency && ($defaultCurrency == $c['code']) ||
|
||||||
|
($defaultCurrencyId && ($defaultCurrencyId == $c['currency_id']))) {
|
||||||
|
$currency = $c['code'];
|
||||||
|
$currency_id = $c['currency_id'];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if no site currency configured set first available currency
|
||||||
|
if (! $currency) {
|
||||||
|
$c = reset($currencies);
|
||||||
|
$currency = $c['code'];
|
||||||
|
$currency_id = $c['currency_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->session->set('currency', $currency);
|
||||||
|
$this->session->set('currency_id', $currency_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->global['currency'] = $currency;
|
||||||
|
$this->global['currency_id'] = $currency_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
//$this->session->delete('csrf');
|
||||||
|
//$this->session = Session::getInstance();
|
||||||
|
//$this->request = Request::getInstance();
|
||||||
|
$view = View :: getInstance();
|
||||||
|
$view->removeVattrs(false);
|
||||||
|
|
||||||
|
if (isset($this->request->get['errors']) && $this->request->get['errors']) {
|
||||||
|
$view->errors['get'] = htmlspecialchars($this->request->get['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request->get['success']) && $this->request->get['success']) {
|
||||||
|
$view->success['get'] = htmlspecialchars($this->request->get['success']);
|
||||||
|
}
|
||||||
|
|
||||||
|
//prevent admin loading in iframe
|
||||||
|
$this->response->addHeader('X-Frame-Options', 'SAMEORIGIN');
|
||||||
|
$this->response->addHeader('X-Content-Type-Options', 'nosniff');
|
||||||
|
|
||||||
|
if (! $this->session->get('csrf')) {
|
||||||
|
$this->session->set('csrf', Str::random());
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin = Admin::current();
|
||||||
|
|
||||||
|
if (! $admin) {
|
||||||
|
return $this->requireLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->checkCsrf();
|
||||||
|
|
||||||
|
if (($site_id = ($this->request->post['site'] ?? false)) && is_numeric($site_id)) {
|
||||||
|
$this->setSite($site_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$site_id = $this->session->get('site_id');
|
||||||
|
|
||||||
|
if (! $site_id) {
|
||||||
|
$site_id = $this->setSite();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->language();
|
||||||
|
$this->currency();
|
||||||
|
$adminPath = \Vvveb\adminPath();
|
||||||
|
|
||||||
|
//change site status (live, under maintenance etc)
|
||||||
|
if ($state = ($this->request->post['state'] ?? false)) {
|
||||||
|
if (Admin::hasPermission('settings/site/save')) {
|
||||||
|
if (Sites::setSiteDataById($site_id, 'state', $state)) {
|
||||||
|
$this->session->set('state', $state);
|
||||||
|
PageCache::getInstance()->purge();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message = __('Your role does not have permission to access this action!');
|
||||||
|
$this->view->errors[] = $message;
|
||||||
|
$this->view->adminPath = $adminPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = $this->request->get['page'] ?? 1;
|
||||||
|
$limit = $this->request->get['limit'] ?? 10;
|
||||||
|
|
||||||
|
$this->global['site_id'] = $site_id;
|
||||||
|
$this->global['host'] = $this->session->get('host');
|
||||||
|
$this->global['site_url'] = $this->session->get('site_url');
|
||||||
|
$this->global['admin_id'] = $admin['admin_id'];
|
||||||
|
$this->global['state'] = $state;
|
||||||
|
$this->global['page'] = $page;
|
||||||
|
$this->global['start'] = ($page - 1) * $limit;
|
||||||
|
$this->global['limit'] = $limit;
|
||||||
|
|
||||||
|
//Check permissions
|
||||||
|
$className = get_class($this);
|
||||||
|
|
||||||
|
if ($className != 'Vvveb\Controller\Error403') {
|
||||||
|
$this->permission();
|
||||||
|
$this->setPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
//load plugins for active site if safe mode is not selected
|
||||||
|
if (! isset($admin['safemode']) || ! $admin['safemode']) {
|
||||||
|
Plugins :: loadPlugins($site_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($errors = $this->session->get('errors')) {
|
||||||
|
if (is_array($errors)) {
|
||||||
|
$view->errors = ($view->errors ?? []) + $errors;
|
||||||
|
} else {
|
||||||
|
$view->errors['session'] = $errors;
|
||||||
|
}
|
||||||
|
$this->session->delete('errors');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($success = $this->session->get('success')) {
|
||||||
|
if (is_array($success)) {
|
||||||
|
$view->success = ($view->success ?? []) + $success;
|
||||||
|
} else {
|
||||||
|
$view->success['session'] = $success;
|
||||||
|
}
|
||||||
|
$this->session->delete('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
//don't initialize menu items for CLI
|
||||||
|
if (defined('CLI')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheDriver = Cache :: getInstance();
|
||||||
|
$cacheKey = $this->global['admin_id'] . '.' . $this->global['site_id'] . '.' . $this->global['language_id'];
|
||||||
|
|
||||||
|
if ($menu = $cacheDriver->get('admin-menu', $cacheKey)) {
|
||||||
|
} else {
|
||||||
|
$menu = \Vvveb\config('admin-menu', []);
|
||||||
|
|
||||||
|
//custom posts -- add to menu
|
||||||
|
$this->taxonomies = $this->getTaxonomies();
|
||||||
|
$posts_menu = $this->customPost();
|
||||||
|
$menu = arrayInsertArrayAfter('edit', $menu, $posts_menu);
|
||||||
|
|
||||||
|
//products - add to menu
|
||||||
|
$products_menu = $this->customProduct();
|
||||||
|
$menu = arrayInsertArrayAfter('sales', $menu, $products_menu);
|
||||||
|
|
||||||
|
list($menu) = Event::trigger(__CLASS__, __FUNCTION__ . '-menu', $menu);
|
||||||
|
|
||||||
|
$urls = [];
|
||||||
|
$this->getPermissionsFromUrl($menu, $urls);
|
||||||
|
$permissions = Admin::hasPermission($urls);
|
||||||
|
//$urls = array_map(fn ($value) => $value ? ($permissions[$value] ?? false) : false, $urls);
|
||||||
|
$urls = array_map(function ($value) use ($permissions) { return $value ? ($permissions[$value] ?? false) : false; }, $urls);
|
||||||
|
$this->setPermissionsFromUrl($menu, $urls);
|
||||||
|
|
||||||
|
$cacheDriver->set('admin-menu', $cacheKey, $menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->menu = $menu;
|
||||||
|
$view->global = $this->global;
|
||||||
|
|
||||||
|
//send to view for button visibillity check
|
||||||
|
$this->view->actionPermissions = $this->actionPermissions ?? [];
|
||||||
|
$this->view->modulePermissions = $this->modulePermissions ?? [];
|
||||||
|
|
||||||
|
$view->adminPath = $adminPath;
|
||||||
|
$view->mediaPath = PUBLIC_PATH . 'media';
|
||||||
|
$view->publicPath = PUBLIC_PATH . 'media';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function redirect($url = '/', $parameters = [], $stop = true) {
|
||||||
|
$redirect = \Vvveb\url($url, $parameters);
|
||||||
|
|
||||||
|
if ($redirect) {
|
||||||
|
$url = $redirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
header("Location: $url");
|
||||||
|
|
||||||
|
if ($stop) {
|
||||||
|
$this->session->close();
|
||||||
|
FrontController::closeConnections();
|
||||||
|
PageCache::getInstance()->cleanUp();
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method if the action requires login, if the user is not logged in, a login form will be shown.
|
||||||
|
* If Keycloak auto-login is enabled, redirects to Keycloak instead of showing login form.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function requireLogin() {
|
||||||
|
// Check if Keycloak auto-login is enabled
|
||||||
|
$keycloakAutoLogin = \Vvveb\config('keycloak.auto_login', false);
|
||||||
|
|
||||||
|
// Check if user explicitly wants classic login (via ?classic_login=1 parameter)
|
||||||
|
$forceClassicLogin = isset($this->request->get['classic_login']) && $this->request->get['classic_login'] == '1';
|
||||||
|
|
||||||
|
// If Keycloak auto-login is enabled and user doesn't force classic login, redirect to Keycloak
|
||||||
|
if ($keycloakAutoLogin && !$forceClassicLogin) {
|
||||||
|
$adminPath = \Vvveb\adminPath();
|
||||||
|
$redirectUrl = $adminPath . 'index.php?module=keycloak/login';
|
||||||
|
|
||||||
|
// Preserve the original URL for redirect after login
|
||||||
|
$originalUrl = $_SERVER['REQUEST_URI'] ?? '';
|
||||||
|
if ($originalUrl && strpos($originalUrl, 'module=keycloak') === false) {
|
||||||
|
$redirectUrl .= '&redirect=' . urlencode($originalUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ' . $redirectUrl);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, show classic login form
|
||||||
|
//return \Vvveb\System\Core\FrontController::redirect('user/login');
|
||||||
|
//$view = view :: getInstance();
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$this->view->redir = $_SERVER['REQUEST_URI'] ?? '';
|
||||||
|
$this->view->adminPath = $admin_path;
|
||||||
|
$this->view->action = "{$admin_path}index.php?module=user/login";
|
||||||
|
$this->view->template('user/login.html');
|
||||||
|
|
||||||
|
$this->view->render();
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method on form posts to protect against csrf attacks.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function checkCsrf() {
|
||||||
|
if (! defined('CLI') &&
|
||||||
|
(($method = $this->request->getMethod()) == 'post') &&
|
||||||
|
(! ($csrf = $this->session->get('csrf')) || ! ($postCsrf = ($this->request->post['csrf'] ?? false)) || ($csrf != $postCsrf))) {
|
||||||
|
$this->notFound('Invalid csrf!', 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a "Not found", "Internal server error" or "Permission denied" page.
|
||||||
|
*
|
||||||
|
* @param unknown_type $code
|
||||||
|
* @param mixed $statusCode
|
||||||
|
* @param mixed $service
|
||||||
|
* @param mixed $message
|
||||||
|
*/
|
||||||
|
protected function notFound($message = false, $statusCode = 404, $service = false) {
|
||||||
|
return FrontController::notFound($service, $message, $statusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the documentation link for current page.
|
||||||
|
*
|
||||||
|
* @param unknown_type $code
|
||||||
|
* @param null|mixed $module
|
||||||
|
* @param null|mixed $action
|
||||||
|
*/
|
||||||
|
protected function getDocUrlForPage($module = null, $action = null) {
|
||||||
|
$module = $module ?? $this->request->get['module'] ?? '';
|
||||||
|
$action = $action ?? $this->request->get['origaction'] ?? '';
|
||||||
|
$type = $type ?? $this->request->get['type'] ?? '';
|
||||||
|
$action = $action ? '/' . $action : '';
|
||||||
|
$url = 'https://docs.vvveb.com/';
|
||||||
|
|
||||||
|
if ($type == 'post' || $type == 'page'/* || $type == 'product'*/) {
|
||||||
|
$type = $type ? '/' . $type : '';
|
||||||
|
} else {
|
||||||
|
$type = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$documentionList = include DIR_SYSTEM . 'data/documentation-map.php';
|
||||||
|
|
||||||
|
if (isset($documentionList[$module . $action . $type])) {
|
||||||
|
$url .= $documentionList[$module . $action . $type];
|
||||||
|
} else {
|
||||||
|
$url .= str_replace('/', '-', $module . $action . $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToHelp() {
|
||||||
|
$url = $this->getDocUrlForPage();
|
||||||
|
|
||||||
|
return header("Location: $url");
|
||||||
|
}
|
||||||
|
}
|
||||||
311
admin/controller/content/autocomplete-trait.php
Normal file
311
admin/controller/content/autocomplete-trait.php
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use \Vvveb\Sql\categorySQL;
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
use function Vvveb\url;
|
||||||
|
|
||||||
|
trait AutocompleteTrait {
|
||||||
|
function categoriesAutocomplete() {
|
||||||
|
$categories = new CategorySQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
$type = trim($this->request->get['type'] ?? '');
|
||||||
|
$post_type = $this->request->get['post_type'] ?? '';
|
||||||
|
|
||||||
|
$results = $categories->getCategories([
|
||||||
|
'post_type' => $post_type,
|
||||||
|
'type' => $type,
|
||||||
|
'search' => '%' . $text . '%',
|
||||||
|
] + $this->global);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['categories'])) {
|
||||||
|
foreach ($results['categories'] as $category) {
|
||||||
|
$search[$category['taxonomy_item_id']] = $category['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function manufacturersAutocomplete() {
|
||||||
|
$manufacturers = new \Vvveb\Sql\ManufacturerSQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'search' => '%' . $text . '%',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $manufacturers->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['manufacturer'])) {
|
||||||
|
foreach ($results['manufacturer'] as $manufacturer) {
|
||||||
|
$manufacturer['image'] = Images::image($manufacturer['image'], 'manufacturer');
|
||||||
|
$search[$manufacturer['manufacturer_id']] = '<img width="32" height="32" src="' . $manufacturer['image'] . '"> ' . $manufacturer['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function vendorsAutocomplete() {
|
||||||
|
$vendors = new \Vvveb\Sql\VendorSQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'search' => '%' . $text . '%',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $vendors->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['vendor'])) {
|
||||||
|
foreach ($results['vendor'] as $vendor) {
|
||||||
|
$vendor['image'] = Images::image($vendor['image'], 'vendor');
|
||||||
|
$search[$vendor['vendor_id']] = '<img width="32" height="32" src="' . $vendor['image'] . '"> ' . $vendor['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function urlAutocomplete() {
|
||||||
|
$products = new \Vvveb\Sql\ProductSQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
$type = $this->request->get['type'] ?? 'card'; //'key-value'
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'limit' => 5,
|
||||||
|
'like' => $text,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
unset($options['admin_id']);
|
||||||
|
$results = $products->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
$pages = [
|
||||||
|
'index/index' => __('Home'),
|
||||||
|
'product/index' => __('Shop'),
|
||||||
|
'content' => __('Blog'),
|
||||||
|
'user/index' => __('User'),
|
||||||
|
'user/login/index' => __('Login'),
|
||||||
|
'user/signup/index' => __('Signup'),
|
||||||
|
'cart/cart/index' => __('Cart'),
|
||||||
|
'checkout/checkout/index' => __('Checkout'),
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($pages as $route => $name) {
|
||||||
|
if (stripos($name, $text) !== false) {
|
||||||
|
$url = url($route);
|
||||||
|
$search[$url] = $name;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($results['product'])) {
|
||||||
|
foreach ($results['product'] as $product) {
|
||||||
|
$product['image'] = Images::image($product['image'], 'product', 'thumb');
|
||||||
|
$url = url('product/product/index', ['slug'=> $product['slug'], 'product_id' => $product['product_id']]);
|
||||||
|
|
||||||
|
if ($type == 'card') {
|
||||||
|
$search[] = [
|
||||||
|
'type' => 'cardimage',
|
||||||
|
'src' => $product['image'],
|
||||||
|
'text' => $product['name'],
|
||||||
|
'value'=> '<a href="' . $url . '">' . $product['name'] . '</a>',
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$search[$url] = '<img width="32" height="32" src="' . $product['image'] . '"> ' . $product['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($search) < 5) {
|
||||||
|
$posts = new \Vvveb\Sql\PostSQL();
|
||||||
|
$results = $posts->getAll($options);
|
||||||
|
|
||||||
|
if (isset($results['post'])) {
|
||||||
|
foreach ($results['post'] as $post) {
|
||||||
|
$post['image'] = Images::image($post['image'], 'post', 'thumb');
|
||||||
|
$url = url('content/post/index', ['slug'=> $post['slug'], 'post_id' => $post['post_id']]);
|
||||||
|
|
||||||
|
if ($type == 'card') {
|
||||||
|
$search[] = [
|
||||||
|
'type' => 'cardimage',
|
||||||
|
'src' => $post['image'],
|
||||||
|
'text' => $post['name'],
|
||||||
|
'value'=> '<a href="' . $url . '">' . $post['name'] . '</a>',
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$search[$url] = '<img width="32" height="32" src="' . $post['image'] . '"> ' . $post['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function productsAutocomplete() {
|
||||||
|
$products = new \Vvveb\Sql\ProductSQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'like' => $text,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
unset($options['admin_id']);
|
||||||
|
$results = $products->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['product'])) {
|
||||||
|
foreach ($results['product'] as $product) {
|
||||||
|
$product['image'] = Images::image($product['image'], $this->object);
|
||||||
|
$search[$product[$this->object . '_id']] = '<img width="32" height="32" src="' . $product['image'] . '"> ' . $product['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function adminsAutocomplete() {
|
||||||
|
$admins = new \Vvveb\Sql\AdminSQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'status' => 1,
|
||||||
|
'search' => $text,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $admins->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['admin'])) {
|
||||||
|
foreach ($results['admin'] as $admin) {
|
||||||
|
$text = '';
|
||||||
|
|
||||||
|
if (isset($admin['avatar'])) {
|
||||||
|
$admin['avatar'] = Images::image($admin['avatar'], 'admin');
|
||||||
|
$text = '<img width="32" height="32" src="' . $admin['avatar'] . '"> ';
|
||||||
|
}
|
||||||
|
$text .= $admin['username'] . ' (' . $admin['first_name'] . ' ' . $admin['last_name'] . ')';
|
||||||
|
|
||||||
|
$search[$admin['admin_id']] = $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function attributesAutocomplete() {
|
||||||
|
$attributes = new \Vvveb\Sql\AttributeSQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'search' => $text,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $attributes->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['attribute'])) {
|
||||||
|
foreach ($results['attribute'] as $attribute) {
|
||||||
|
$text = '';
|
||||||
|
|
||||||
|
$text .= $attribute['name'] . ' (' . $attribute['group'] . ')';
|
||||||
|
|
||||||
|
$search[$attribute['attribute_id']] = $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function optionValuesAutocomplete() {
|
||||||
|
$values = new \Vvveb\Sql\Option_valueSQL();
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'option_id' => trim($this->request->get['option_id']),
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $values->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['option_value'])) {
|
||||||
|
foreach ($results['option_value'] as $value) {
|
||||||
|
$text = '';
|
||||||
|
|
||||||
|
$text .= $value['name'];
|
||||||
|
|
||||||
|
$search[$value['option_value_id']] = $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function digitalAssetsAutocomplete() {
|
||||||
|
$digital_assets = new \Vvveb\Sql\Digital_assetSQL();
|
||||||
|
$text = trim($this->request->get['text'] ?? '');
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'search' => $text,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $digital_assets->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['digital_asset'])) {
|
||||||
|
foreach ($results['digital_asset'] as $digital_asset) {
|
||||||
|
$text = '';
|
||||||
|
|
||||||
|
$text .= $digital_asset['name'] . ' (' . $digital_asset['file'] . ')';
|
||||||
|
|
||||||
|
$search[$digital_asset['digital_asset_id']] = $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
}
|
||||||
138
admin/controller/content/categories.php
Normal file
138
admin/controller/content/categories.php
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use \Vvveb\Sql\categorySQL;
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Categories extends Base {
|
||||||
|
function delete() {
|
||||||
|
$taxonomy_item_id = $this->request->post['taxonomy_item_id'] ?? false;
|
||||||
|
$categories = new categorySQL();
|
||||||
|
|
||||||
|
if (is_numeric($taxonomy_item_id)) {
|
||||||
|
$taxonomy_item_id = [$taxonomy_item_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($taxonomy_item_id && $categories->deleteTaxonomyItem(['taxonomy_item_id' => $taxonomy_item_id])) {
|
||||||
|
echo __('Item removed!');
|
||||||
|
}
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reorder() {
|
||||||
|
$data = $this->request->post;
|
||||||
|
$categories = new categorySQL();
|
||||||
|
|
||||||
|
//['taxonomy_items' => $data]
|
||||||
|
if ($categories->updateTaxonomyItems($data)) {
|
||||||
|
echo __('Items reordered!');
|
||||||
|
}
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$data = $this->request->post;
|
||||||
|
$data['taxonomy_id'] = $data['taxonomy_id'] ?? $this->request->get['taxonomy_id'];
|
||||||
|
$data['taxonomy_item']['taxonomy_id'] = $data['taxonomy_id'];
|
||||||
|
$data['taxonomy_item']['sort_order'] = $data['sort_order'] ?? 0;
|
||||||
|
|
||||||
|
$categories = new categorySQL();
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'taxonomy_item_content' => $data['taxonomy_item_content'],
|
||||||
|
'taxonomy_item' => $data['taxonomy_item'],
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
if (isset($data['taxonomy_item_id']) && $data['taxonomy_item_id']) {
|
||||||
|
$options['taxonomy_item_id'] = $data['taxonomy_item_id'];
|
||||||
|
$results = $categories->editTaxonomyItem($options);
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
echo __('Item saved!');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$results = $categories->addTaxonomyItem($options);
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
echo __('Item added!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = $this->view;
|
||||||
|
$categories = new categorySQL();
|
||||||
|
|
||||||
|
$page = $this->request->get['page'] ?? 1;
|
||||||
|
$type = $this->request->get['type'] ?? '';
|
||||||
|
$taxonomy_id = $this->request->get['taxonomy_id'] ?? false;
|
||||||
|
$limit = 1000;
|
||||||
|
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=media/media';
|
||||||
|
$this->view->scanUrl = "$controllerPath&action=scan";
|
||||||
|
$this->uploadUrl = "$controllerPath&action=upload";
|
||||||
|
|
||||||
|
if ($taxonomy_id) {
|
||||||
|
$options = [
|
||||||
|
'start' => ($page - 1) * $limit,
|
||||||
|
'limit' => $limit,
|
||||||
|
'taxonomy_id' => $taxonomy_id,
|
||||||
|
'post_type' => $type,
|
||||||
|
'type' => 'categories',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$view->taxonomy_id = $taxonomy_id;
|
||||||
|
|
||||||
|
$results = $categories->getCategoriesAllLanguages($options);
|
||||||
|
|
||||||
|
foreach ($results['categories'] as &$taxonomy_item) {
|
||||||
|
$langs = $taxonomy_item['languages'] ? json_decode($taxonomy_item['languages'], true) : [];
|
||||||
|
$taxonomy_item['languages'] = [];
|
||||||
|
|
||||||
|
if (isset($taxonomy_item['image'])) {
|
||||||
|
$taxonomy_item['image_url'] = Images::image($taxonomy_item['image'], 'taxonomy_item');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($langs) {
|
||||||
|
foreach ($langs as $lang) {
|
||||||
|
$taxonomy_item['languages'][$lang['language_id']] = $lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
$taxonomy_item['name'] = $taxonomy_item['languages'][$this->global['language_id']]['name'] ?? $langs[0]['name'] ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->set($results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
admin/controller/content/comment.php
Normal file
69
admin/controller/content/comment.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\model;
|
||||||
|
|
||||||
|
class Comment extends Base {
|
||||||
|
protected $type = 'comment';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$type = $this->type;
|
||||||
|
$comment_id = $this->request->get[$type . '_id'] ?? false;
|
||||||
|
$comment = $this->request->post[$type] ?? false;
|
||||||
|
|
||||||
|
if ($comment) {
|
||||||
|
$comments = model($type);
|
||||||
|
|
||||||
|
if ($comment_id) {
|
||||||
|
$result = $comments->edit([$type => $comment, $type . '_id' => $comment_id]);
|
||||||
|
} else {
|
||||||
|
$result = $comments->add([$type => $comment]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result && isset($result[$type])) {
|
||||||
|
$this->view->success[] = __('Saved!');
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$type = $this->type;
|
||||||
|
$comments = model($type);
|
||||||
|
$comment_id = $this->request->get[$type . '_id'] ?? false;
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'type' => $this->type,
|
||||||
|
$type . '_id' => $comment_id,
|
||||||
|
] + $this->global;
|
||||||
|
unset($options['user_id']);
|
||||||
|
|
||||||
|
$this->view->$type = $comments->get($options);
|
||||||
|
}
|
||||||
|
}
|
||||||
122
admin/controller/content/comments.php
Normal file
122
admin/controller/content/comments.php
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use function Vvveb\model;
|
||||||
|
use Vvveb\Sql\commentSQL;
|
||||||
|
use Vvveb\System\CacheManager;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Comments extends Listing {
|
||||||
|
protected $type = 'comment';
|
||||||
|
|
||||||
|
protected $list = 'comment';
|
||||||
|
|
||||||
|
protected $module = 'content';
|
||||||
|
|
||||||
|
protected $listController = 'comments';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$type = $this->type;
|
||||||
|
$comment_id = $this->request->get[$type . '_id'] ?? $this->request->post[$type . '_id'] ?? false;
|
||||||
|
$status = $this->request->get['newstatus'] ?? $this->request->post['newstatus'] ?? false;
|
||||||
|
|
||||||
|
if ($comment_id) {
|
||||||
|
$comments = model($type);
|
||||||
|
|
||||||
|
if ($comments->edit([$type => ['status' => (int) $status], $type . '_id' => $comment_id])) {
|
||||||
|
//CacheManager::delete($type);
|
||||||
|
CacheManager::delete();
|
||||||
|
$this->view->success[] = sprintf(__('%s status changed!'), humanReadable(__($type)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = View :: getInstance();
|
||||||
|
$type = $this->type;
|
||||||
|
$controller = $this->controller ?? $type;
|
||||||
|
$listController = $this->listController ?? $controller;
|
||||||
|
$module = $this->module;
|
||||||
|
$list = $this->list ?? $type . 's';
|
||||||
|
$status = $this->request->get['status'] ?? '';
|
||||||
|
|
||||||
|
$comment_status = [
|
||||||
|
0 => __('Pending'),
|
||||||
|
1 => __('Approved'),
|
||||||
|
2 => __('Spam'),
|
||||||
|
3 => __('Trash'),
|
||||||
|
-1 => __('All'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$status = $this->request->get['status'] ?? -1;
|
||||||
|
//$comments = new commentSQL();
|
||||||
|
$comments = model($type);
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'type' => $type,
|
||||||
|
] + $this->global;
|
||||||
|
unset($options['user_id']);
|
||||||
|
|
||||||
|
if ($status > -1) {
|
||||||
|
$options['status'] = $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = $comments->getAll($options);
|
||||||
|
$results[$type] = $results[$type] ?? [];
|
||||||
|
|
||||||
|
foreach ($results[$type] as $id => &$comment) {
|
||||||
|
if (isset($comment['image'])) {
|
||||||
|
$comment['image'] = Images::image($type, $comment['image']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($comment['avatar'])) {
|
||||||
|
$comment['avatar'] = Images::image($comment['avatar'], 'user');
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = ['module' => "$module/$listController", 'action' => 'save', 'status' => $status, $type . '_id' => $comment[$type . '_id']];
|
||||||
|
$postUrl = ['module' => "$module/$controller", $type . '_id' => $comment[$type . '_id']];
|
||||||
|
$comment['edit-url'] = \Vvveb\url($postUrl);
|
||||||
|
$comment['delete-url'] = \Vvveb\url(['module' => "$module/$listController", 'action' => 'delete'] + $url);
|
||||||
|
$comment['approve-url'] = \Vvveb\url(['newstatus' => 1] + $url);
|
||||||
|
$comment['spam-url'] = \Vvveb\url(['newstatus' => 2] + $url);
|
||||||
|
$comment['trash-url'] = \Vvveb\url(['newstatus' => 3] + $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
$statuses = "{$type}_status";
|
||||||
|
$view->$list = $results[$type];
|
||||||
|
$view->count = $results['count'];
|
||||||
|
$view->$statuses = $comment_status;
|
||||||
|
$view->module = $module;
|
||||||
|
$view->controller = $controller;
|
||||||
|
|
||||||
|
$view->limit = $options['limit'];
|
||||||
|
$view->status = $status;
|
||||||
|
}
|
||||||
|
}
|
||||||
569
admin/controller/content/edit.php
Normal file
569
admin/controller/content/edit.php
Normal file
@ -0,0 +1,569 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\getSetting;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use function Vvveb\model;
|
||||||
|
use function Vvveb\sanitizeHTML;
|
||||||
|
use function Vvveb\setSetting;
|
||||||
|
use function Vvveb\slugify;
|
||||||
|
use Vvveb\Sql\CategorySQL;
|
||||||
|
use Vvveb\Sql\Field_GroupSQL;
|
||||||
|
use Vvveb\Sql\FieldSQL;
|
||||||
|
use Vvveb\System\Cache;
|
||||||
|
use Vvveb\System\CacheManager;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
use Vvveb\System\Traits\FieldGroup;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
use Vvveb\System\Validator;
|
||||||
|
|
||||||
|
class Edit extends Base {
|
||||||
|
protected $type = 'post';
|
||||||
|
|
||||||
|
protected $object = 'post';
|
||||||
|
|
||||||
|
protected $revisions = true;
|
||||||
|
|
||||||
|
use TaxonomiesTrait, AutocompleteTrait, SitesTrait, FieldGroup;
|
||||||
|
|
||||||
|
function getThemeFolder() {
|
||||||
|
return DIR_THEMES . Sites::getTheme(SITE_ID) ?? 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
function fields() {
|
||||||
|
$field_group_id = 1;
|
||||||
|
$options = ['type' => $this->object, 'subtype' => $this->type, 'limit' => 1000];
|
||||||
|
$fieldGroup = new Field_GroupSQL();
|
||||||
|
$fieldGroups = $fieldGroup->getAll($options + $this->global)['field_group'] ?? [];
|
||||||
|
|
||||||
|
$langsFields = [];
|
||||||
|
$field_group_id = [];
|
||||||
|
|
||||||
|
foreach ($fieldGroups as $group) {
|
||||||
|
$field_group_id[$group['field_group_id']] = $group['field_group_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field_group_id) {
|
||||||
|
$post_id = $this->request->get[$this->object . '_id'] ?? false;
|
||||||
|
|
||||||
|
$field = new FieldSQL();
|
||||||
|
$fields = $field->getAll(['field_group_id' => $field_group_id, $this->object . '_id' => $post_id, 'limit' => 1000] + $this->global);
|
||||||
|
$langsFields = [];
|
||||||
|
|
||||||
|
if ($fields['count'] > 0) {
|
||||||
|
foreach ($fields['field'] as &$field) {
|
||||||
|
$input['settings'] = json_decode($field['settings'], true);
|
||||||
|
$input['validation'] = json_decode($field['validation'], true);
|
||||||
|
$input['presentation'] = json_decode($field['presentation'], true);
|
||||||
|
|
||||||
|
$field['class'] = 'row mb-3';
|
||||||
|
$field['label-class'] = 'form-label';
|
||||||
|
$field['label'] = $input['settings']['label'] ?? '';
|
||||||
|
$field['instructions'] = $input['presentation']['instructions'] ?? '';
|
||||||
|
$field['placeholder'] = $input['settings']['placeholder'] ?? '';
|
||||||
|
|
||||||
|
foreach (['value', 'default'] as $key) {
|
||||||
|
if (isset($field[$key]) && $field[$key]) {
|
||||||
|
if ($field[$key][0] == '{') {
|
||||||
|
$field[$key] = json_decode($field[$key], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$field['value'] = $field[$key];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->view->languagesList as $code => $lang) {
|
||||||
|
$field['name'] = 'field[' . $lang['language_id'] . '][' . $field['field_id'] . ']';
|
||||||
|
$field['field'] = $this->renderFields2([$field]);
|
||||||
|
|
||||||
|
$groupName = $fieldGroups[$field['field_group_id']]['name'];
|
||||||
|
$langsFields[$lang['language_id']][$groupName][] = $field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->view->fields = $langsFields;
|
||||||
|
$this->view->count = $fields['count'] ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = $this->view;
|
||||||
|
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$postOptions = [];
|
||||||
|
$post = [];
|
||||||
|
$post_id = $this->request->get[$this->object . '_id'] ?? $this->request->post[$this->object . '_id'] ?? false;
|
||||||
|
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=media/media';
|
||||||
|
$view->scanUrl = "$controllerPath&action=scan";
|
||||||
|
$view->uploadUrl = "$controllerPath&action=upload";
|
||||||
|
$view->linkUrl = $admin_path . 'index.php?module=content/post&action=urlAutocomplete';
|
||||||
|
$theme = Sites::getTheme(SITE_ID) ?? 'default';
|
||||||
|
$view->themeCss = '';
|
||||||
|
|
||||||
|
if (file_exists(DIR_THEMES . "$theme/css/admin-post-editor.css")) {
|
||||||
|
$view->themeCss .= PUBLIC_PATH . "themes/$theme/css/admin-post-editor.css";
|
||||||
|
} else {
|
||||||
|
if (file_exists(DIR_THEMES . "$theme/css/style.css")) {
|
||||||
|
$view->themeCss .= PUBLIC_PATH . "themes/$theme/css/style.css";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (['custom.css', 'fonts.css'] as $css) {
|
||||||
|
if (file_exists(DIR_THEMES . "$theme/css/$css")) {
|
||||||
|
$view->themeCss .= ',' . PUBLIC_PATH . "themes/$theme/css/$css";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//$view->themeCss = PUBLIC_PATH . "themes/$theme/css/style.css";
|
||||||
|
|
||||||
|
$viewCapability = 'view_other_posts';
|
||||||
|
|
||||||
|
if ($this->object == 'product') {
|
||||||
|
$viewCapability = 'view_other_products';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($post_id) {
|
||||||
|
$postOptions[$this->object . '_id'] = (int)$post_id;
|
||||||
|
} else {
|
||||||
|
if (isset($this->request->get['slug'])) {
|
||||||
|
$postOptions['slug'] = $this->request->get['slug'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request->get['type'])) {
|
||||||
|
$this->type = $this->request->get['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($postOptions) {
|
||||||
|
$posts = model($this->object);
|
||||||
|
|
||||||
|
$postOptions['type'] = $this->type;
|
||||||
|
$options = $postOptions + $this->global;
|
||||||
|
|
||||||
|
if (Admin::hasCapability($viewCapability)) {
|
||||||
|
unset($options['admin_id']);
|
||||||
|
} else {
|
||||||
|
$options['admin_id'] = $this->global['admin_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//get all languages
|
||||||
|
//unset($options['language_id']);
|
||||||
|
$post = $posts->get($options);
|
||||||
|
|
||||||
|
if (! $post) {
|
||||||
|
$message = sprintf(__('%s not found!'), humanReadable(__($this->type)));
|
||||||
|
$this->notFound(['message' => $message, 'title' => $message]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//featured image
|
||||||
|
if (isset($post['image'])) {
|
||||||
|
$post['image_url'] = Images::image($post['image'], $this->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
//gallery
|
||||||
|
if (isset($post[$this->object . '_image'])) {
|
||||||
|
$post['images'] = Images::images($post[$this->object . '_image'], $this->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
//$productImages = $posts->getImages($postOptions);
|
||||||
|
} else {
|
||||||
|
$post['image_url'] = Images::image('',$this->object);
|
||||||
|
$post['updated_at'] = date('Y-m-d H:i:s', time());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (isset($post['updated_at'])) {
|
||||||
|
$post['updated_at'] = str_replace(' ', 'T', $post['updated_at']);
|
||||||
|
} else {
|
||||||
|
$post['updated_at'] = date("Y-m-d\TH:i:s", isset($post['updated_at']) && $post['updated_at'] ? strtotime($post['updated_at']) : time());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
$this->type = $post['type'] ?? $this->type;
|
||||||
|
|
||||||
|
if ($this->object == 'product') {
|
||||||
|
$route = "product/{$this->type}/index";
|
||||||
|
$altRoute = "product/{$this->object}/index";
|
||||||
|
$controller = 'product';
|
||||||
|
} else {
|
||||||
|
$route = "content/{$this->type}/index";
|
||||||
|
$altRoute = "content/{$this->object}/index";
|
||||||
|
$controller = 'content';
|
||||||
|
$stickyPosts = getSetting('posts', 'sticky') ?? [];
|
||||||
|
//$post['sticky'] = in_array($post['post_id'], $stickyPosts);
|
||||||
|
$post['sticky'] = isset($post['post_id']) && isset($stickyPosts[$post['post_id']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->revisions) {
|
||||||
|
$revisions = model($this->object . '_content_revision');
|
||||||
|
}
|
||||||
|
|
||||||
|
//get site host for current selected site to use for absolute url
|
||||||
|
$url = ['host' => $this->global['host']];
|
||||||
|
|
||||||
|
$revisionsUrl = \Vvveb\url(['module' => "$controller/revisions", 'object' => $this->object, 'type' => $this->type, $this->object . '_id' => $post_id]);
|
||||||
|
$name = '';
|
||||||
|
|
||||||
|
if (isset($post[$this->object . '_content'])) {
|
||||||
|
foreach ($post[$this->object . '_content'] as &$content) {
|
||||||
|
if (! isset($post['url'])) {
|
||||||
|
$post['url'] = \Vvveb\url($route, ['slug'=> $content['slug'], $this->object . '_id' => $post_id] + $url);
|
||||||
|
$post['relative-url'] = \Vvveb\url($route, ['slug'=> $content['slug'], $this->object . '_id' => $post_id]);
|
||||||
|
|
||||||
|
if (! $post['url'] || $post['url'] == '//' . $this->global['site_url']) {
|
||||||
|
$post['url'] = \Vvveb\url($altRoute, ['slug'=> $content['slug'], $this->object . '_id' => $post_id] + $url);
|
||||||
|
$post['relative-url'] = \Vvveb\url($altRoute, ['slug'=> $content['slug'], $this->object . '_id' => $post_id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$language = [];
|
||||||
|
|
||||||
|
if ($content['language_id'] != $this->global['default_language_id']) {
|
||||||
|
$code = 'en_US';
|
||||||
|
|
||||||
|
foreach ($this->view->languagesList as $code => $lang) {
|
||||||
|
if ($lang['language_id'] == $content['language_id']) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$language = ['language' => $code];
|
||||||
|
} else {
|
||||||
|
$name = $content['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$content['url'] = \Vvveb\url($route, $content + $language + $url);
|
||||||
|
$content['revision_count'] = 0;
|
||||||
|
|
||||||
|
if (! $content['url'] || $content['url'] == '//' . $this->global['site_url']) {
|
||||||
|
$content['url'] = \Vvveb\url($altRoute, $content + $language + $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($revisions) {
|
||||||
|
$revision = $revisions->getAll([$this->object . '_id' => $post_id, 'language_id' => $content['language_id']]);
|
||||||
|
|
||||||
|
if ($revision) {
|
||||||
|
foreach ($revision[$this->object . '_content_revision'] as &$rev) {
|
||||||
|
$rev['preview-url'] = $content['url'] . '?revision=preview&created_at=' . $rev['created_at'] . '&language_id=' . $content['language_id'];
|
||||||
|
$rev['compare-url'] = $revisionsUrl . '&created_at=' . $rev['created_at'] . '&language_id=' . $content['language_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$content['revision_count'] = $revision['count'];
|
||||||
|
$content['revision'] = $revision[$this->object . '_content_revision'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$type_name = humanReadable(__($this->type));
|
||||||
|
|
||||||
|
$defaultTemplate = \Vvveb\getCurrentTemplate();
|
||||||
|
$template = isset($post['template']) && $post['template'] ? $post['template'] : $defaultTemplate;
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
|
||||||
|
$design_url = '';
|
||||||
|
|
||||||
|
if (isset($post['url'])) {
|
||||||
|
$design_url = \Vvveb\url(['module' => 'editor/editor', 'name' => urlencode($name), 'url' => $post['relative-url'], 'template' => $template], false);
|
||||||
|
$post['design_url'] = $design_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! file_exists($themeFolder . DS . $template)) {
|
||||||
|
if ($template == $defaultTemplate) {
|
||||||
|
$view->template_missing = sprintf(__('Template missing, choose existing template or %screate global template%s for %s.'), '<a href="' . $design_url . '" target="_blank">', '</a>', $type_name);
|
||||||
|
} else {
|
||||||
|
$view->template_missing = sprintf(__('Template missing, %screate template%s for this %s.'), '<a href="' . $design_url . '" target="_blank">', '</a>', $type_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->type != 'page') {
|
||||||
|
$view->taxonomies = $this->taxonomies($post[$this->object . '_id'] ?? false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sites = $post[$this->object . '_to_site'] ?? [];
|
||||||
|
|
||||||
|
if ($sites) {
|
||||||
|
$sites = array_keys($sites);
|
||||||
|
} else {
|
||||||
|
if (! $post_id) {
|
||||||
|
$sites[] = $this->global['site_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->sitesList = $this->sites($sites);
|
||||||
|
|
||||||
|
list($post, $post_id, $this->type) = Event :: trigger(__CLASS__,__FUNCTION__, $post, $post_id, $this->type);
|
||||||
|
|
||||||
|
$object = $this->object;
|
||||||
|
$view->$object = $post;
|
||||||
|
$view->status = ['publish' => 'Publish', 'draft' => 'Draft', 'pending' => 'Pending', 'private' => 'Private', 'password' => 'Password', 'future' => 'Future'];
|
||||||
|
|
||||||
|
$view->templates = Cache::getInstance()->cache(APP, 'template-list-' . $theme, function () use ($theme) {
|
||||||
|
return \Vvveb\getTemplateList($theme, ['email']);
|
||||||
|
}, 604800);
|
||||||
|
|
||||||
|
$view->themeFonts = Cache::getInstance()->cache(APP, 'fonts-list-' . $theme, function () use ($theme) {
|
||||||
|
$fonts = \Vvveb\System\Media\Font::themeFonts($theme);
|
||||||
|
$names = [];
|
||||||
|
|
||||||
|
if ($fonts) {
|
||||||
|
foreach ($fonts as $font) {
|
||||||
|
if (isset($font['font-family'])) {
|
||||||
|
$names[$font['font-family']] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}, 604800);
|
||||||
|
|
||||||
|
$this->fields();
|
||||||
|
|
||||||
|
//$validator = new Validator([$this->object]);
|
||||||
|
//$view->validatorJson = $validator->getJSON();
|
||||||
|
$view->type = __($this->type);
|
||||||
|
$view->type_name = $type_name;
|
||||||
|
$view->posts_list_url = \Vvveb\url(['module' => $this->list, 'type' => $this->type]);
|
||||||
|
$view->revisions_url = $revisionsUrl;
|
||||||
|
$view->oEmbedProxyUrl = $admin_path . 'index.php?module=editor/editor&action=oEmbedProxy';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addCategory($taxonomy_id, $name) {
|
||||||
|
$categories = new CategorySQL();
|
||||||
|
$cat = $categories->addCategory([
|
||||||
|
'taxonomy_item' => $this->global + [
|
||||||
|
'taxonomy_id' => $taxonomy_id,
|
||||||
|
],
|
||||||
|
'taxonomy_item_content' => $this->global + ['slug'=> slugify($name), 'name' => $name, 'content' => ''],
|
||||||
|
] + $this->global);
|
||||||
|
|
||||||
|
return $category_id = $cat['taxonomy_item'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function add() {
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$view = view :: getInstance();
|
||||||
|
$post_id = $this->request->get[$this->object . '_id'] ?? $this->request->post[$this->object . '_id'] ?? false;
|
||||||
|
$this->{$this->object . '_id'} = $post_id;
|
||||||
|
$publicPath = \Vvveb\publicUrlPath();
|
||||||
|
|
||||||
|
if (isset($this->request->get['type'])) {
|
||||||
|
$this->type = $this->request->get['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$validator = new Validator([$this->object]);
|
||||||
|
$validatorContent = new Validator([$this->object . '_content']);
|
||||||
|
|
||||||
|
if (
|
||||||
|
(($errors = $validator->validate($this->request->post)) === true) &&
|
||||||
|
(($errors = $validatorContent->validate(current($this->request->post[$this->object . '_content']))) === true)
|
||||||
|
) {
|
||||||
|
$posts = model($this->object);
|
||||||
|
|
||||||
|
$post = [];
|
||||||
|
|
||||||
|
$post = $this->request->post;
|
||||||
|
|
||||||
|
foreach ($post[$this->object . '_content'] as &$content) {
|
||||||
|
$content['name'] = strip_tags($content['name']);
|
||||||
|
$content['content'] = sanitizeHTML($content['content']);
|
||||||
|
|
||||||
|
if (isset($content['excerpt'])) {
|
||||||
|
$content['excerpt'] = sanitizeHTML($content['excerpt']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (isset($post['updated_at'])) {
|
||||||
|
$post['updated_at'] = str_replace(' ', 'T', $post['updated_at']);
|
||||||
|
} else {
|
||||||
|
$post['updated_at'] = date("Y-m-d\TH:i:s", time());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//process tags
|
||||||
|
if (isset($post['tag'])) {
|
||||||
|
foreach ($post['tag'] as $listId => $tags) {
|
||||||
|
foreach ($tags as $tagId => $tag) {
|
||||||
|
//existing tag add to post taxonomy_item list
|
||||||
|
if (is_numeric($tagId)) {
|
||||||
|
//$post['taxonomy_item_id'][] = $tagId;
|
||||||
|
} else {
|
||||||
|
//add new taxonomy_item
|
||||||
|
$tagId = $this->addCategory($listId, $tag);
|
||||||
|
}
|
||||||
|
$post['taxonomy_item_id'][] = $tagId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//process fields
|
||||||
|
$post_field_value = [];
|
||||||
|
|
||||||
|
if (isset($post['field'])) {
|
||||||
|
foreach ($post['field'] as $language_id => $fields) {
|
||||||
|
foreach ($fields as $field_id => $value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$value = json_encode($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$post_field_value[] = ['field_id' => $field_id, 'language_id' => $language_id, 'value' => $value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$site_id = $this->request->post['site'] ?? []; //[$this->global['site_id']];
|
||||||
|
|
||||||
|
$post = $post + $this->global;
|
||||||
|
$new = false;
|
||||||
|
|
||||||
|
if ($post_id) {
|
||||||
|
$editCapability = 'edit_other_posts';
|
||||||
|
|
||||||
|
if ($this->object == 'product') {
|
||||||
|
$editCapability = 'edit_other_products';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Admin::hasCapability($editCapability)) {
|
||||||
|
//unset($data['admin_id']);
|
||||||
|
} else {
|
||||||
|
//$data['admin_id'] = $this->global['admin_id'];
|
||||||
|
$view->errors[] = __('Permission denied!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$post[$this->object . '_id'] = (int)$post_id;
|
||||||
|
$data = [
|
||||||
|
$this->object => $post,
|
||||||
|
$this->object . '_id' => $post_id,
|
||||||
|
$this->object . '_content' => $post[$this->object . '_content'],
|
||||||
|
'taxonomy_item_id' => $post['taxonomy_item_id'] ?? [],
|
||||||
|
'post_field_value' => $post_field_value,
|
||||||
|
'site_id' => $site_id,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$result = $posts->edit($data);
|
||||||
|
|
||||||
|
if ($result >= 0) {
|
||||||
|
$this->view->success['get'] = ucfirst($this->type) . ' ' . __('saved') . '!';
|
||||||
|
|
||||||
|
$stickyPosts = getSetting('posts', 'sticky') ?? [];
|
||||||
|
|
||||||
|
if (isset($post['sticky']) && ! isset($stickyPosts[$post_id])) {
|
||||||
|
$stickyPosts[$post_id] = $post_id;
|
||||||
|
setSetting('posts', 'sticky', $stickyPosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($stickyPosts[$post_id]) && ! isset($post['sticky'])) {
|
||||||
|
unset($stickyPosts[$post_id]);
|
||||||
|
setSetting('posts', 'sticky', $stickyPosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ($this->revisions) {
|
||||||
|
$revisions = model($this->object . '_content_revision');
|
||||||
|
|
||||||
|
//foreach ($post[$this->object . '_content'] as &$content) {
|
||||||
|
foreach ($this->request->post[$this->object . '_content'] as &$content) {
|
||||||
|
if (isset($content['has_changes']) && $content['has_changes'] == 1) {
|
||||||
|
$revisions->add(['revision' => [
|
||||||
|
$this->object . '_id' => $post_id,
|
||||||
|
'language_id' => $content['language_id'],
|
||||||
|
'content' => $content['content'],
|
||||||
|
'created_at' => date("Y-m-d\TH:i:s", time()),
|
||||||
|
] + $this->global]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors = [$posts->error];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$post['type'] = $this->type;
|
||||||
|
//$post['created_at'] = $post['updated_at'];
|
||||||
|
if (isset($post['updated_at']) && ! $post['updated_at']) {
|
||||||
|
unset($post['updated_at'], $post[$this->object . '_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$add = [
|
||||||
|
$this->object => $post,
|
||||||
|
$this->object . '_content' => $post[$this->object . '_content'],
|
||||||
|
'taxonomy_item_id' => $post['taxonomy_item_id'] ?? [],
|
||||||
|
'post_field_value' => $post_field_value,
|
||||||
|
'site_id' => $site_id,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$return = $posts->add($add);
|
||||||
|
$id = $return[$this->object] ?? false;
|
||||||
|
|
||||||
|
if (! $id) {
|
||||||
|
$view->errors = [$posts->error];
|
||||||
|
} else {
|
||||||
|
$this->request->get[$this->object . '_id'] = $id;
|
||||||
|
|
||||||
|
$post_id = $id;
|
||||||
|
$new = true;
|
||||||
|
|
||||||
|
$message = ucfirst($this->type) . ' ' . __('saved') . '!';
|
||||||
|
$view->success['get'] = $message;
|
||||||
|
|
||||||
|
if (isset($post['sticky'])) {
|
||||||
|
$stickyPosts = getSetting('posts', 'sticky');
|
||||||
|
$stickyPosts[$post_id] = $post_id;
|
||||||
|
setSetting('posts', 'sticky', $stickyPosts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($post[$this->object . '_image'])) {
|
||||||
|
$productImage = $this->object . 'Image';
|
||||||
|
|
||||||
|
foreach ($post[$this->object . '_image'] as &$image) {
|
||||||
|
$image = str_replace($publicPath . 'media/','', $image);
|
||||||
|
}
|
||||||
|
|
||||||
|
$posts->$productImage([$this->object . '_id' => $post_id ? $post_id : 0, $this->object . '_image' => $post[$this->object . '_image']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($post, $post_id, $this->type) = Event :: trigger(__CLASS__,__FUNCTION__, $post, $post_id, $this->type);
|
||||||
|
|
||||||
|
CacheManager::clearObjectCache('component', $this->object);
|
||||||
|
CacheManager::clearObjectCache('component', $this->object . 's');
|
||||||
|
CacheManager::clearPageCache();
|
||||||
|
|
||||||
|
if ($new) {
|
||||||
|
$this->redirect(['module'=>$this->module, $this->object . '_id' => $id, 'type' => $this->type, 'success' => $message], [], false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$view->errors = $errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
282
admin/controller/content/menus.php
Normal file
282
admin/controller/content/menus.php
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use function Vvveb\sanitizeHTML;
|
||||||
|
use Vvveb\Sql\menuSQL;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
|
||||||
|
class Menus extends Categories {
|
||||||
|
use SitesTrait;
|
||||||
|
|
||||||
|
function deleteMenu() {
|
||||||
|
$view = $this->view;
|
||||||
|
$menu_id = $this->request->post['menu_id'] ?? $this->request->get['menu_id'] ?? false;
|
||||||
|
$menu = new menuSQL();
|
||||||
|
|
||||||
|
if (is_numeric($menu_id)) {
|
||||||
|
$menu_id = [$menu_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($menu_id && ($result = $menu->deleteMenu(['menu_id' => $menu_id]))) {
|
||||||
|
if ($result['menu'] > 0) {
|
||||||
|
$success = __('Menu deleted!');
|
||||||
|
} else {
|
||||||
|
$success = __('Menu not found!');
|
||||||
|
}
|
||||||
|
$view->success[] = $success;
|
||||||
|
} else {
|
||||||
|
$view->errors = [$menu->error];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined('CLI')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
$menu_item_id = $this->request->post['menu_item_id'] ?? false;
|
||||||
|
$view = $this->view;
|
||||||
|
$menus = new menuSQL();
|
||||||
|
|
||||||
|
if ($menu_item_id) {
|
||||||
|
if (is_numeric($menu_item_id)) {
|
||||||
|
$menu_item_id = [$menu_item_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
//will fail on mysql 5
|
||||||
|
$result = $menus->deleteMenuItemRecursive(['menu_item_id' => $menu_item_id]);
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
//older mysql versions don't have recursive CTE
|
||||||
|
$result = $menus->deleteMenuItem(['menu_item_id' => $menu_item_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result['menu_item'] > 0) {
|
||||||
|
$success = __('Item deleted!');
|
||||||
|
} else {
|
||||||
|
$success = __('Item not found!');
|
||||||
|
}
|
||||||
|
$view->success[] = $success;
|
||||||
|
echo $success;
|
||||||
|
} else {
|
||||||
|
$view->errors = [$menus->error ?? ''];
|
||||||
|
echo $menus->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function reorder() {
|
||||||
|
$data = $this->request->post;
|
||||||
|
$menus = new menuSQL();
|
||||||
|
|
||||||
|
//['menu_items' => $data]
|
||||||
|
if ($menus->updateMenuItems($data)) {
|
||||||
|
echo __('Items reordered!');
|
||||||
|
}
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$data = $this->request->post;
|
||||||
|
|
||||||
|
$menus = new menuSQL();
|
||||||
|
|
||||||
|
if (isset($data['item_id']) && ! is_numeric($data['item_id'])) {
|
||||||
|
unset($data['item_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['menu_item_content'])) {
|
||||||
|
foreach ($data['menu_item_content'] as &$lang) {
|
||||||
|
$lang['content'] = sanitizeHTML($lang['content']);
|
||||||
|
|
||||||
|
// if autocomplete set text as default name for languages
|
||||||
|
if (isset($data['item_id_text'])) {
|
||||||
|
$lang['name'] = $data['item_id_text'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = [];
|
||||||
|
$success = true;
|
||||||
|
$menu_item_id = false;
|
||||||
|
|
||||||
|
if (isset($data['menu_item_id']) && $data['menu_item_id']) {
|
||||||
|
$results = $menus->editMenuItem(['menu_item' => $data, 'menu_item_id' => $data['menu_item_id']]);
|
||||||
|
$menu_item_id = $data['menu_item_id'];
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
$message = __('Item saved!');
|
||||||
|
} else {
|
||||||
|
$message = __('Error!');
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$results = $menus->addMenuItem(['menu_item' => $data]);
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
$menu_item_id = $results['menu_item'];
|
||||||
|
$message = __('Item added!');
|
||||||
|
} else {
|
||||||
|
$message = __('Error!');
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$response += ['success' => $success, 'message' => $message, 'menu_item_id' => $menu_item_id];
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
function menu() {
|
||||||
|
$menuId = $this->request->get['menu_id'] ?? false;
|
||||||
|
$menu_data = $this->request->post['menu_data'] ?? false;
|
||||||
|
$site_id = $this->request->post['site'] ?? []; //[$this->global['site_id']];
|
||||||
|
$view = $this->view;
|
||||||
|
$menus = new menuSQL();
|
||||||
|
|
||||||
|
$page = $this->request->get['page'] ?? 1;
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
if ($menuId) {
|
||||||
|
$options = [
|
||||||
|
'menu_id' => $menuId,
|
||||||
|
'limit' => 100000,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $menus->getMenuAllLanguages($options);
|
||||||
|
|
||||||
|
foreach ($results['categories'] as &$menu) {
|
||||||
|
$langs = $menu['languages'] ? json_decode($menu['languages'], true) : [];
|
||||||
|
$menu['languages'] = [];
|
||||||
|
|
||||||
|
if ($langs) {
|
||||||
|
foreach ($langs as $lang) {
|
||||||
|
$menu['languages'][$lang['language_id']] = $lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
$menu['name'] = $menu['languages'][$this->global['language_id']]['name'] ?? $langs[0]['name'] ?? '';
|
||||||
|
$menu['content'] = $menu['languages'][$this->global['language_id']]['content'] ?? $langs[0]['content'] ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($menu_data) {
|
||||||
|
$menu_data = $menu_data + ['site_id' => $site_id] + $options;
|
||||||
|
|
||||||
|
$return = $menus->editMenu($menu_data);
|
||||||
|
$id = $return['menu'];
|
||||||
|
$menu_site = $return['menu_to_site'];
|
||||||
|
|
||||||
|
if (! $id && ! $menu_site) {
|
||||||
|
$view->errors = ['No changes!'];
|
||||||
|
} else {
|
||||||
|
$view->success[] = __('Menu saved!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$results['menu_data'] = $menus->get($options);
|
||||||
|
} else {
|
||||||
|
if ($menu_data) {
|
||||||
|
$menu_data = $menu_data + $this->global;
|
||||||
|
$return = $menus->addMenu(['menu' => $menu_data, 'site_id' => $site_id]);
|
||||||
|
|
||||||
|
$id = $return['menu'];
|
||||||
|
|
||||||
|
if (! $id) {
|
||||||
|
$view->errors = [$menu->error];
|
||||||
|
} else {
|
||||||
|
$success = __('Menu saved!');
|
||||||
|
$view->success[] = $success;
|
||||||
|
$this->redirect(['module'=>'content/menus', 'action' => 'menu', 'menu_id' => $id, 'success' => $success]);
|
||||||
|
$menu_data['menu_id'] = $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$results['menu_data'] = $menu_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->set($results);
|
||||||
|
$view->menu_id = $menuId;
|
||||||
|
$sites = $results['menu_data']['menu_to_site'] ?? [];
|
||||||
|
|
||||||
|
if ($sites) {
|
||||||
|
$sites = array_keys($sites);
|
||||||
|
} else {
|
||||||
|
if (! $menuId) {
|
||||||
|
$sites[] = $this->global['site_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->sitesList = $this->sites($sites);
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=media/media';
|
||||||
|
$view->scanUrl = "$controllerPath&action=scan";
|
||||||
|
$view->uploadUrl = "$controllerPath&action=upload";
|
||||||
|
$view->linkUrl = $admin_path . 'index.php?module=content/post&action=urlAutocomplete';
|
||||||
|
$theme = Sites::getTheme(SITE_ID) ?? 'default';
|
||||||
|
$view->themeCss = PUBLIC_PATH . "themes/$theme/css/admin-post-editor.css";
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = $this->view;
|
||||||
|
$menus = new menuSQL();
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'limit' => 10000,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $menus->getAll($options);
|
||||||
|
|
||||||
|
if (isset($results['menu'])) {
|
||||||
|
foreach ($results['menu'] as &$menu) {
|
||||||
|
$url = ['module' => 'content/menus', 'action' => 'menu', 'menu_id' => $menu['menu_id']];
|
||||||
|
$menu['url'] = \Vvveb\url($url);
|
||||||
|
$menu['edit-url'] = $menu['url'];
|
||||||
|
$menu['delete-url'] = \Vvveb\url(['action' => 'deleteMenu'] + $url);
|
||||||
|
|
||||||
|
$langs = isset($menu['languages']) ? json_decode($menu['languages'], true) : [];
|
||||||
|
$menu['languages'] = [];
|
||||||
|
|
||||||
|
if ($langs) {
|
||||||
|
foreach ($langs as $lang) {
|
||||||
|
$menu['languages'][$lang['language_id']] = $lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
$menu['name'] = $langs[0]['name'] ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$results['menus'] = $results['menu'];
|
||||||
|
unset($results['menu']);
|
||||||
|
}
|
||||||
|
$view->set($results);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
admin/controller/content/post.php
Normal file
39
admin/controller/content/post.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
class Post extends Edit {
|
||||||
|
protected $type = 'post';
|
||||||
|
|
||||||
|
protected $object = 'post';
|
||||||
|
|
||||||
|
protected $module = 'content/post';
|
||||||
|
|
||||||
|
protected $list = 'content/posts';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
parent::save();
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
}
|
||||||
271
admin/controller/content/posts.php
Normal file
271
admin/controller/content/posts.php
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use Vvveb\Sql\PostSQL;
|
||||||
|
use Vvveb\System\Cache;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
use function Vvveb\url;
|
||||||
|
|
||||||
|
class Posts extends Listing {
|
||||||
|
protected $type = 'post';
|
||||||
|
|
||||||
|
//check for other modules permission like post and editor to enable links like save/delete etc
|
||||||
|
protected $additionalPermissionCheck = ['content/post/save'];
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if (isset($this->request->get['type'])) {
|
||||||
|
$this->type = $this->request->get['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function duplicate() {
|
||||||
|
$post_id = $this->request->post['post_id'] ?? false;
|
||||||
|
|
||||||
|
if ($post_id) {
|
||||||
|
$this->posts = new PostSQL();
|
||||||
|
$data = $this->posts->get(['post_id' => $post_id, 'type' => $this->type]);
|
||||||
|
$old_id = $data['post_id'];
|
||||||
|
|
||||||
|
unset($data['post_id']);
|
||||||
|
$id = rand(1, 1000);
|
||||||
|
|
||||||
|
foreach ($data['post_content'] as &$content) {
|
||||||
|
unset($content['post_id']);
|
||||||
|
$content['name'] .= ' [' . __('duplicate') . ']';
|
||||||
|
$content['slug'] .= '-' . __('duplicate') . "-$old_id-$id";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['post_to_taxonomy_item'])) {
|
||||||
|
foreach ($data['post_to_taxonomy_item'] as &$item) {
|
||||||
|
$taxonomy_item_id[] = $item['taxonomy_item_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['post_to_site'])) {
|
||||||
|
foreach ($data['post_to_site'] as &$item) {
|
||||||
|
$site_id[] = $item['site_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
$result = $this->posts->add([
|
||||||
|
'post' => $data,
|
||||||
|
'post_content' => $data['post_content'],
|
||||||
|
'taxonomy_item_id' => $taxonomy_item_id ?? [],
|
||||||
|
'site_id' => $site_id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($result && isset($result['post'])) {
|
||||||
|
$post_id = $result['post'];
|
||||||
|
$url = url(['module' => 'content/post', 'post_id' => $post_id, 'type' => $this->type]);
|
||||||
|
|
||||||
|
$success = ucfirst($this->type) . __(' duplicated!');
|
||||||
|
$success .= sprintf(' <a href="%s">%s</a>', $url, __('Edit') . " {$this->type}");
|
||||||
|
$this->view->success['get'] = $success;
|
||||||
|
//$this->session->set('success', $success);
|
||||||
|
//$this->redirect(['module' => 'content/posts', 'type' => $this->type], [], false);
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error duplicating %s!'), $this->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
$post_id = $this->request->post['post_id'] ?? false;
|
||||||
|
|
||||||
|
if ($post_id) {
|
||||||
|
if (is_numeric($post_id)) {
|
||||||
|
$post_id = [$post_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->posts = new postSQL();
|
||||||
|
$options = [
|
||||||
|
'post_id' => $post_id, 'type' => $this->type,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$result = $this->posts->delete($options);
|
||||||
|
|
||||||
|
if ($result && isset($result['post'])) {
|
||||||
|
$this->view->success[] = ucfirst($this->type) . __(' deleted!');
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error deleting %s!'), $this->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function archives($options) {
|
||||||
|
$options['interval'] = 'month';
|
||||||
|
|
||||||
|
$archives = $this->posts->getArchives($options);
|
||||||
|
|
||||||
|
$return = [];
|
||||||
|
|
||||||
|
$df = false;
|
||||||
|
|
||||||
|
if (class_exists('\IntlDateFormatter')) {
|
||||||
|
$dt = new \DateTime();
|
||||||
|
$df = new \IntlDateFormatter(\Vvveb\getLanguage(), \IntlDateFormatter::NONE, \IntlDateFormatter::NONE, NULL, NULL, 'MMMM');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($archives['archives'] as $index => &$archive) {
|
||||||
|
if (isset($archive['month'])) {
|
||||||
|
$monthNum = $archive['month'];
|
||||||
|
//$dateObj = \DateTime::createFromFormat('!m', $monthNum);
|
||||||
|
//$monthName = $dateObj->format('F');
|
||||||
|
|
||||||
|
$archive['month_text'] = $monthNum;
|
||||||
|
|
||||||
|
if ($df) {
|
||||||
|
$archive['month_text'] = ucfirst(datefmt_format($df, $dt));
|
||||||
|
$dt->setDate(0, $archive['month'], 0);
|
||||||
|
} else {
|
||||||
|
$archive['month_text'] = date('F',mktime(0,0,0,$monthNum,1,$archive['year']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$name =
|
||||||
|
(isset($archive['day']) ? $archive['day'] . ' ' : '') .
|
||||||
|
(isset($archive['month']) ? $archive['month_text'] . ' ' : '') .
|
||||||
|
(isset($archive['year']) ? $archive['year'] . ' ' : '');
|
||||||
|
|
||||||
|
$archive['month'] = sprintf('%02d', $archive['month']);
|
||||||
|
|
||||||
|
$return[$archive['year'] . '/' . $archive['month']] = $name;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
$return = [];
|
||||||
|
|
||||||
|
if (isset($archives['archives'])) {
|
||||||
|
foreach ($archives['archives'] as $index => &$archive) {
|
||||||
|
if (isset($archive['month'])) {
|
||||||
|
$monthNum = $archive['month'];
|
||||||
|
|
||||||
|
$archive['month_text'] = $monthNum;
|
||||||
|
|
||||||
|
if ($df) {
|
||||||
|
$dt->setDate(0, $archive['month'], 0);
|
||||||
|
$archive['month_text'] = ucfirst(datefmt_format($df, $dt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$archive['month'] = sprintf('%02d', $archive['month']);
|
||||||
|
$name =
|
||||||
|
(isset($archive['month']) ? $archive['month_text'] . ' ' : '') .
|
||||||
|
(isset($archive['year']) ? $archive['year'] . ' ' : '');
|
||||||
|
|
||||||
|
$return[$archive['year'] . '/' . $archive['month']] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = $this->view;
|
||||||
|
$this->posts = new postSQL();
|
||||||
|
|
||||||
|
$this->type = $this->request->get['type'] ?? 'post';
|
||||||
|
$this->filter = array_filter($this->request->get['filter'] ?? []);
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'type' => $this->type,
|
||||||
|
'comment_count' => true,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
if (Admin::hasCapability('view_other_posts')) {
|
||||||
|
unset($options['admin_id']);
|
||||||
|
} else {
|
||||||
|
$options['admin_id'] = $this->global['admin_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$options += $this->filter;
|
||||||
|
|
||||||
|
//override admin if admin_id filter set
|
||||||
|
if (isset($this->filter['admin_id'])) {
|
||||||
|
$options['admin_id'] = $this->filter['admin_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->filter['archives']) && $this->filter['archives']) {
|
||||||
|
$archives = explode('/', $this->filter['archives']);
|
||||||
|
$options['year'] = $archives[0];
|
||||||
|
$options['month'] = $archives[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = $this->posts->getAll($options);
|
||||||
|
|
||||||
|
$defaultTemplate = "content/{$this->type}.html";
|
||||||
|
|
||||||
|
if ($results && isset($results['post'])) {
|
||||||
|
foreach ($results['post'] as $id => &$post) {
|
||||||
|
if (isset($post['image'])) {
|
||||||
|
$post['image'] = Images::image($post['image'], 'post');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $post['name'] && ($post['language_id'] != $this->global['default_language_id'])) {
|
||||||
|
$post['name'] = '[' . __('No translation') . ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = ['module' => 'content/post', 'post_id' => $post['post_id'], 'type' => $post['type']];
|
||||||
|
$adminPath = \Vvveb\adminPath();
|
||||||
|
$template = $post['template'] ? $post['template'] : $defaultTemplate;
|
||||||
|
$post['url'] = url($url);
|
||||||
|
$post['edit-url'] = $post['url'];
|
||||||
|
$post['admin-url'] = url(['module' => 'content/posts']) . '&filter[admin_id_text]=' . $post['username'] . ' &filter[admin_id]=' . $post['admin_id'];
|
||||||
|
$post['delete-url'] = url(['module' => 'content/posts', 'action' => 'delete'] + $url); // + ['post_id[]' => $post['post_id']]);
|
||||||
|
$post['duplicate-url'] = url(['module' => 'content/posts', 'action' => 'duplicate'] + $url); // + ['post_id' => $post['post_id']]);
|
||||||
|
$post['view-url'] = url("content/{$this->type}/index", $post + $url + ['host' => $this->global['host']]);
|
||||||
|
$relativeUrl = url("content/{$this->type}/index", $post + $url);
|
||||||
|
$post['design-url'] = url(['module' => 'editor/editor', 'name' => urlencode($post['name'] ?? ''), 'url' => $relativeUrl, 'template' => $template], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//archives for filter
|
||||||
|
$cache = Cache::getInstance();
|
||||||
|
$archives = $cache->cache('posts',"archives.{$this->type}.{$this->global['site_id']}" ,
|
||||||
|
function () use (&$options) {
|
||||||
|
return $this->archives($options) ?? [];
|
||||||
|
}, 259200);
|
||||||
|
|
||||||
|
$view->set($results);
|
||||||
|
$view->status = ['publish' => 'Publish', 'pending' => 'Pending', 'draft' => 'Draft', 'private' => 'Private', 'password' => 'Password'];
|
||||||
|
$view->archives = $archives;
|
||||||
|
$view->filter = $this->filter;
|
||||||
|
$view->limit = $options['limit'];
|
||||||
|
$view->type = $this->type;
|
||||||
|
$view->addUrl = url(['module' => 'content/post', 'type' => $this->type]);
|
||||||
|
$view->type_name = humanReadable(__($this->type));
|
||||||
|
$view->type_name_plural = humanReadable(__($view->type . 's'));
|
||||||
|
}
|
||||||
|
}
|
||||||
147
admin/controller/content/revisions.php
Normal file
147
admin/controller/content/revisions.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use function Vvveb\model;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Revisions extends Base {
|
||||||
|
protected $type = 'post';
|
||||||
|
|
||||||
|
protected $object = 'post';
|
||||||
|
|
||||||
|
//check for other modules permission like revision and editor to enable links like save/delete etc
|
||||||
|
protected $additionalPermissionCheck = ['content/revisions/save'];
|
||||||
|
|
||||||
|
function merge() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if (isset($this->request->get['type'])) {
|
||||||
|
$this->type = $this->request->get['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request->get['object'])) {
|
||||||
|
$this->object = $this->request->get['object'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->revisions = model($this->object . '_content_revision');
|
||||||
|
$this->post = model($this->object);
|
||||||
|
|
||||||
|
$this->options = ['type' => $this->type];
|
||||||
|
|
||||||
|
foreach ([$this->object . '_id', 'language_id', 'created_at'] as $param) {
|
||||||
|
if (isset($this->request->get[$param])) {
|
||||||
|
$this->options[$param] = $this->request->get[$param];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
$results = $this->revisions->delete($this->options + $this->global);
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
$message[] = __('Revision deleted!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$content = $this->request->post['content'] ?? false;
|
||||||
|
|
||||||
|
if ($content) {
|
||||||
|
$result = $this->post->editContent(
|
||||||
|
[$this->type . '_content' => ['content' => $content]] +
|
||||||
|
$this->options +
|
||||||
|
$this->global
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$this->view->success[] = ucfirst($this->type) . ' ' . __('saved') . '!';
|
||||||
|
} else {
|
||||||
|
$view->errors = [$post->error];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function revision() {
|
||||||
|
$view = $this->view;
|
||||||
|
$results = $this->revisions->get($this->options);
|
||||||
|
$revision = [];
|
||||||
|
|
||||||
|
if ($results && $results['content']) {
|
||||||
|
foreach (['content', 'created_at', 'display_name'] as $key) {
|
||||||
|
$revision[$key] = $results[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = $this->view;
|
||||||
|
$modelName = $this->object . '_content_revision';
|
||||||
|
$revisions = model($modelName);
|
||||||
|
$this->options += $this->global;
|
||||||
|
$allOptions = $this->options;
|
||||||
|
unset($allOptions['created_at']);
|
||||||
|
|
||||||
|
$revisions = $this->revisions->getAll($allOptions); // all post/product revisions
|
||||||
|
$revision = $this->revisions->get($this->options); // latest or selected revision
|
||||||
|
$post = $this->post->get($this->options); // post/product content
|
||||||
|
|
||||||
|
if (isset($post['image'])) {
|
||||||
|
$post['image'] = $post['image'] = Images::image($post['image'], $this->object, 'thumb');
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = [
|
||||||
|
'revisions' => $revisions[$modelName] ?? [],
|
||||||
|
'revision' => $revision ?? [],
|
||||||
|
'post' => $post ?? [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$view->set($results);
|
||||||
|
|
||||||
|
$view->limit = $this->options['limit'];
|
||||||
|
$view->type = $this->type;
|
||||||
|
$view->options = $this->options;
|
||||||
|
$view->revisionUrl = \Vvveb\url([
|
||||||
|
'module' => 'content/revisions',
|
||||||
|
'action' => 'revision',
|
||||||
|
'type' => $this->type,
|
||||||
|
'object' => $this->object,
|
||||||
|
$this->object . '_id' => $this->options[$this->object . '_id'], ]);
|
||||||
|
$view->type_name = humanReadable(__($this->type));
|
||||||
|
$view->type_name_plural = humanReadable(__($view->type . 's'));
|
||||||
|
}
|
||||||
|
}
|
||||||
55
admin/controller/content/sites-trait.php
Normal file
55
admin/controller/content/sites-trait.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use Vvveb\Sql\SiteSQL;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
|
||||||
|
trait SitesTrait {
|
||||||
|
function sites($selectedSites = []) {
|
||||||
|
$sites = new SiteSQL();
|
||||||
|
|
||||||
|
$options = [];
|
||||||
|
|
||||||
|
if (Admin::hasCapability('edit_other_sites')) {
|
||||||
|
//unset($options['site_id']);
|
||||||
|
} else {
|
||||||
|
$options['site_id'] = Admin :: siteAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = $sites->getAll(
|
||||||
|
$options + [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 100,
|
||||||
|
]
|
||||||
|
)['site'] ?? [];
|
||||||
|
|
||||||
|
if ($results && $selectedSites) {
|
||||||
|
foreach ($results as &$site) {
|
||||||
|
$site['selected'] = in_array($site['site_id'], $selectedSites);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
101
admin/controller/content/tag.php
Normal file
101
admin/controller/content/tag.php
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use Vvveb\Sql\categorySQL;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Tag extends Base {
|
||||||
|
protected $type = 'tag';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$taxonomy_item_id = $this->request->get['taxonomy_item_id'] ?? false;
|
||||||
|
$taxonomy_id = $this->request->get['taxonomy_id'];
|
||||||
|
$post_type = $this->request->get['type'] ?? '';
|
||||||
|
$tag = $this->request->post['tag'] ?? false;
|
||||||
|
|
||||||
|
if ($tag) {
|
||||||
|
$tags = new categorySQL();
|
||||||
|
|
||||||
|
if ($taxonomy_item_id) {
|
||||||
|
$result = $tags->editCategory(
|
||||||
|
['taxonomy_item_content' => [$tag + $this->global],
|
||||||
|
'taxonomy_item_id' => $taxonomy_item_id,
|
||||||
|
'taxonomy_item' => ['taxonomy_item_id' => $taxonomy_item_id, 'taxonomy_id' => $taxonomy_id] + $tag,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$result = $tags->addCategory(
|
||||||
|
['taxonomy_item_content' => $tag + $this->global,
|
||||||
|
'taxonomy_item' => ['taxonomy_id' => $taxonomy_id] + $tag,
|
||||||
|
'site_id' => $this->global['site_id'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result && isset($result['taxonomy_item_content'])) {
|
||||||
|
$message = __('Tag saved!');
|
||||||
|
$this->view->success['get'] = $message;
|
||||||
|
|
||||||
|
if (! $taxonomy_item_id) {
|
||||||
|
$this->redirect(['module'=> 'content/tag', 'taxonomy_item_id' => $result['taxonomy_item'], 'taxonomy_id' => $taxonomy_id, 'type' => $post_type, 'success' => $message], [], false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$tags = new categorySQL();
|
||||||
|
$taxonomy_item_id = $this->request->get['taxonomy_item_id'] ?? false;
|
||||||
|
$taxonomy_id = $this->request->get['taxonomy_id'] ?? false;
|
||||||
|
$post_type = $this->request->get['type'] ?? '';
|
||||||
|
|
||||||
|
$view = $this->view;
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=media/media';
|
||||||
|
$view->scanUrl = "$controllerPath&action=scan";
|
||||||
|
$view->uploadUrl = "$controllerPath&action=upload";
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'type' => $this->type,
|
||||||
|
'taxonomy_item_id' => $taxonomy_item_id,
|
||||||
|
'taxonomy_id' => $taxonomy_id,
|
||||||
|
] + $this->global;
|
||||||
|
unset($options['user_id']);
|
||||||
|
|
||||||
|
$tag = $tags->getCategoryBySlug($options);
|
||||||
|
|
||||||
|
if ($tag) {
|
||||||
|
$tag['image_url'] = Images::image($tag['image'], 'tag', 'thumb');
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->taxonomy_id = $taxonomy_id;
|
||||||
|
$view->type = $post_type;
|
||||||
|
$view->status = [1 => __('Enabled'), 0 => __('Disabled')];
|
||||||
|
$view->tag = $tag ?? [];
|
||||||
|
}
|
||||||
|
}
|
||||||
97
admin/controller/content/tags.php
Normal file
97
admin/controller/content/tags.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use Vvveb\Sql\categorySQL;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Tags extends Base {
|
||||||
|
function delete() {
|
||||||
|
$taxonomy_item_id = $this->request->post['taxonomy_item_id'] ?? false;
|
||||||
|
$categories = new categorySQL();
|
||||||
|
|
||||||
|
if (is_numeric($taxonomy_item_id)) {
|
||||||
|
$taxonomy_item_id = [$taxonomy_item_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($taxonomy_item_id && $categories->deleteTaxonomyItem(['taxonomy_item_id' => $taxonomy_item_id])) {
|
||||||
|
$this->view->success[] = 'Item removed!';
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = $this->view;
|
||||||
|
$categories = new categorySQL();
|
||||||
|
|
||||||
|
$page = $this->request->get['page'] ?? 1;
|
||||||
|
$type = $this->request->get['type'] ?? '';
|
||||||
|
$taxonomy_id = $this->request->get['taxonomy_id'] ?? false;
|
||||||
|
$limit = 1000;
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'start' => ($page - 1) * $limit,
|
||||||
|
'limit' => $limit,
|
||||||
|
'post_type' => $type,
|
||||||
|
'taxonomy_id' => $taxonomy_id,
|
||||||
|
'type' => 'tags',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $categories->getCategoriesAllLanguages($options);
|
||||||
|
|
||||||
|
if (isset($results['categories'])) {
|
||||||
|
foreach ($results['categories'] as &$taxonomy_item) {
|
||||||
|
/*
|
||||||
|
$taxonomy_item['languages'] = json_decode($taxonomy_item['languages'], true);
|
||||||
|
$taxonomy_item['name'] = $taxonomy_item['languages'][0]['name'] ?? '';
|
||||||
|
*/
|
||||||
|
$taxonomy_item['image_url'] = Images::image($taxonomy_item['image'], 'tag', 'thumb');
|
||||||
|
|
||||||
|
if (isset($taxonomy_item['languages'])) {
|
||||||
|
$langs = json_decode($taxonomy_item['languages'], true);
|
||||||
|
$taxonomy_item['languages'] = [];
|
||||||
|
|
||||||
|
if ($langs) {
|
||||||
|
foreach ($langs as $lang) {
|
||||||
|
$taxonomy_item['languages'][$lang['language_id']] = $lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
$taxonomy_item['name'] = $taxonomy_item['languages'][$this->global['language_id']]['name'] ?? $langs[0]['name'] ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = ['module' => 'content/tag', 'taxonomy_item_id' => $taxonomy_item['taxonomy_item_id'], 'taxonomy_id' => $taxonomy_id, 'type' => $type];
|
||||||
|
$taxonomy_item['edit-url'] = \Vvveb\url($url);
|
||||||
|
$taxonomy_item['delete-url'] = \Vvveb\url(['module' => 'content/tags', 'action' => 'delete'] + $url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->add_url = \Vvveb\url(['module' => 'content/tag', 'taxonomy_id' => $taxonomy_id, 'type' => $type]);
|
||||||
|
$view->set($results);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
admin/controller/content/taxonomies-trait.php
Normal file
64
admin/controller/content/taxonomies-trait.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use Vvveb\Sql\categorySQL;
|
||||||
|
use Vvveb\Sql\taxonomySQL;
|
||||||
|
|
||||||
|
trait TaxonomiesTrait {
|
||||||
|
protected function taxonomies($post_id = false) {
|
||||||
|
//get taxonomies for post type
|
||||||
|
$taxonomies = new taxonomySQL();
|
||||||
|
$results = $taxonomies->getAll(
|
||||||
|
['post_type' => $this->type]
|
||||||
|
);
|
||||||
|
|
||||||
|
//get taxonomies content
|
||||||
|
if ($results) {
|
||||||
|
$taxonomy_itemSql = new categorySQL();
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'post_type' => $this->type,
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 1000,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
if ($post_id) {
|
||||||
|
$options["{$this->object}_id"] = $post_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($results['taxonomy'])) {
|
||||||
|
foreach ($results['taxonomy'] as $id => &$taxonomy_item) {
|
||||||
|
$taxonomy_item['taxonomy_item'] = [];
|
||||||
|
//for tags don't retrive taxonomies if no post id provided
|
||||||
|
if ($taxonomy_item['type'] != 'tags' || $post_id) {
|
||||||
|
$options = ['taxonomy_id' => $id, 'type' => $taxonomy_item['type']] + $options;
|
||||||
|
$taxonomy_item['taxonomy_item'] = $taxonomy_itemSql->getCategories($options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results['taxonomy'] ?? [];
|
||||||
|
}
|
||||||
|
}
|
||||||
45
admin/controller/content/taxonomy.php
Normal file
45
admin/controller/content/taxonomy.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Content;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
|
||||||
|
class Taxonomy extends Base {
|
||||||
|
function index() {
|
||||||
|
$view = $this->view;
|
||||||
|
$taxonomies = new \Vvveb\Sql\taxonomySQL();
|
||||||
|
$limit = 10000;
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'limit' => $limit,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $taxonomies->getAll($options);
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
foreach ($results as &$category) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$view->taxonomies = $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
admin/controller/crud.php
Normal file
50
admin/controller/crud.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use Vvveb\System\Traits\Crud as CrudTrait;
|
||||||
|
|
||||||
|
class Crud extends Base {
|
||||||
|
use CrudTrait {
|
||||||
|
CrudTrait::index as get;
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$result = $this->get();
|
||||||
|
|
||||||
|
$this->view->{$this->type} = $this->data;
|
||||||
|
|
||||||
|
if ($this->data_id && (! $this->data || (! isset($this->data[$this->type . '_id'])))) {
|
||||||
|
return $this->notFound(sprintf(__('%s not found!'), humanReadable(__($this->type))));
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=media/media';
|
||||||
|
$this->view->scanUrl = "$controllerPath&action=scan";
|
||||||
|
$this->uploadUrl = "$controllerPath&action=upload";
|
||||||
|
|
||||||
|
$this->view->status = [0 => __('Inactive'), 1 => __('Active')];
|
||||||
|
}
|
||||||
|
}
|
||||||
156
admin/controller/editor/autocomplete.php
Normal file
156
admin/controller/editor/autocomplete.php
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Editor;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use Vvveb\Sql\categorySQL;
|
||||||
|
|
||||||
|
class Autocomplete extends Base {
|
||||||
|
private $themeConfig = [];
|
||||||
|
|
||||||
|
function products() {
|
||||||
|
$text = $this->request->get['text'];
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'like' => $text,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
unset($options['admin_id']);
|
||||||
|
$products = new \Vvveb\Sql\ProductSQL();
|
||||||
|
$results = $products->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
foreach ($results['product'] as $product) {
|
||||||
|
$search[$product['product_id']] = $product['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function categories() {
|
||||||
|
$text = $this->request->get['text'];
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'search' => '%' . $text . '%',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$categories = new \Vvveb\Sql\CategorySQL();
|
||||||
|
|
||||||
|
$results = $categories->getCategories($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
foreach ($results['categories'] as $category) {
|
||||||
|
$search[$category['taxonomy_item_id']] = $category['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function manufacturers() {
|
||||||
|
$text = $this->request->get['text'];
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'search' => '%' . $text . '%',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$manufacturers = new \Vvveb\Sql\ManufacturerSQL();
|
||||||
|
|
||||||
|
$results = $manufacturers->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
foreach ($results['manufacturer'] as $manufacturer) {
|
||||||
|
$search[$manufacturer['manufacturer_id']] = $manufacturer['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function posts() {
|
||||||
|
$text = $this->request->get['text'];
|
||||||
|
$type = $this->request->get['type'] ?? 'post';
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'type' => $type,
|
||||||
|
'like' => $text,
|
||||||
|
//'like' => '%' . $text . '%',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
unset($options['admin_id']);
|
||||||
|
$posts = new \Vvveb\Sql\PostSQL();
|
||||||
|
$results = $posts->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
if (isset($results['post'])) {
|
||||||
|
foreach ($results['post'] as $post) {
|
||||||
|
$search[$post['post_id']] = substr($post['name'],0, 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tags() {
|
||||||
|
$taxonomy_id = $this->request->get['taxonomy_id'];
|
||||||
|
$taxonomy = $this->request->get['taxonomy'];
|
||||||
|
$text = $this->request->get['text'];
|
||||||
|
|
||||||
|
$taxonomy_itemSql = new categorySQL();
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'post_id' => $post_id,
|
||||||
|
'language_id' => 1,
|
||||||
|
'site_id' => 1,
|
||||||
|
'taxonomy' => $taxonomy,
|
||||||
|
'start' => 1,
|
||||||
|
'limit' => 100,
|
||||||
|
'search' => '%' . $text . '%',
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $taxonomy_itemSql->getCategories($options + ['taxonomy_id' => $taxonomy_id]);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
foreach ($results['categories'] as $id => &$taxonomy_item) {
|
||||||
|
$search[$taxonomy_item['taxonomy_item_id']] = $taxonomy_item['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
}
|
||||||
|
}
|
||||||
201
admin/controller/editor/code.php
Normal file
201
admin/controller/editor/code.php
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Editor;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\sanitizeFileName;
|
||||||
|
|
||||||
|
class Code extends Base {
|
||||||
|
protected $saveDenyExtensions = ['php', 'tpl'];
|
||||||
|
|
||||||
|
function dirForType($type) {
|
||||||
|
switch ($type) {
|
||||||
|
case 'public':
|
||||||
|
$scandir = DIR_MEDIA;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'plugins':
|
||||||
|
$scandir = DIR_PLUGINS;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'themes':
|
||||||
|
$scandir = DIR_THEMES;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $scandir;
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$type = $this->request->get['type'] ?? false;
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=editor/code';
|
||||||
|
|
||||||
|
if (! $type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->view->scanUrl = "$controllerPath&action=scan&type=$type";
|
||||||
|
$this->view->uploadUrl = "$controllerPath&action=upload&type=$type";
|
||||||
|
$this->view->loadFileUrl = "$controllerPath&action=loadFile&type=$type";
|
||||||
|
$this->view->saveUrl = "$controllerPath&action=save&type=$type";
|
||||||
|
$this->view->type = $type;
|
||||||
|
|
||||||
|
if ($type) {
|
||||||
|
$this->view->mediaPath = str_replace('/media', "/$type", $this->view->mediaPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitizeFileName($file, $type) {
|
||||||
|
if (V_SUBDIR_INSTALL && strpos($file, V_SUBDIR_INSTALL) === 0) {
|
||||||
|
//$path = str_replace(V_SUBDIR_INSTALL, '', $path);
|
||||||
|
$file = substr_replace($file, '', 0, strlen(V_SUBDIR_INSTALL));
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = preg_replace("@^[\/]public@", '', $file);
|
||||||
|
|
||||||
|
if ($type == 'plugins') {
|
||||||
|
$file = DIR_PLUGINS . preg_replace("@^[\/]plugins[\/]@", '', $file);
|
||||||
|
} else {
|
||||||
|
if ($type == 'themes') {
|
||||||
|
$file = DIR_THEMES . preg_replace("@^[\/]themes[\/]@", '', $file);
|
||||||
|
} else {
|
||||||
|
$file = DIR_PUBLIC . $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = sanitizeFileName($file);
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$type = $this->request->get['type'];
|
||||||
|
$file = $this->request->get['file'];
|
||||||
|
$content = $this->request->post['content'];
|
||||||
|
$file = $this->sanitizeFileName($file, $type);
|
||||||
|
|
||||||
|
$message = ['success' => false, 'message' => sprintf(__('Error saving: %s!'), $file)];
|
||||||
|
|
||||||
|
$extension = strtolower(substr($file, strrpos($file, '.') + 1));
|
||||||
|
|
||||||
|
if (in_array($extension, $this->saveDenyExtensions)) {
|
||||||
|
$message = ['success' => false, 'message' => sprintf(__('Saving not allowed for file type %s!'), trim($extension, '.'))];
|
||||||
|
$success = false;
|
||||||
|
} else {
|
||||||
|
if (! is_writable($file)) {
|
||||||
|
$message = ['success' => false, 'message' => sprintf(__('File not writable: %s Check if file has write permission.'), $file)];
|
||||||
|
} else {
|
||||||
|
if (file_put_contents($file, $content)) {
|
||||||
|
$message = ['success' => true, 'message' => __('File saved!')];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadFile() {
|
||||||
|
$type = $this->request->get['type'];
|
||||||
|
$file = $this->request->get['file'];
|
||||||
|
$file = $this->sanitizeFileName($file, $type);
|
||||||
|
|
||||||
|
if (! is_readable($file)) {
|
||||||
|
die("File not readable: $file");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($content = file_get_contents($file)) {
|
||||||
|
die($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
die("Error loading: $file");
|
||||||
|
}
|
||||||
|
|
||||||
|
function scan() {
|
||||||
|
$type = $this->request->get['type'] ?? 'public';
|
||||||
|
$scandir = $this->dirForType($type);
|
||||||
|
|
||||||
|
if (! $scandir) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function scans the files folder recursively, and builds a large array
|
||||||
|
$scan = function ($dir) use ($scandir, &$scan) {
|
||||||
|
$files = [];
|
||||||
|
|
||||||
|
// Is there actually such a folder/file?
|
||||||
|
|
||||||
|
if (file_exists($dir)) {
|
||||||
|
$listdir = @scandir($dir);
|
||||||
|
|
||||||
|
if ($listdir) {
|
||||||
|
foreach ($listdir as $f) {
|
||||||
|
if (! $f || $f[0] == '.' || $f == 'node_modules' || $f == 'vendor') {
|
||||||
|
continue; // Ignore hidden files
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_dir($dir . DS . $f)) {
|
||||||
|
// The path is a folder
|
||||||
|
|
||||||
|
$files[] = [
|
||||||
|
'name' => $f,
|
||||||
|
'type' => 'folder',
|
||||||
|
'path' => str_replace([$scandir, '\\'], ['', '/'], $dir) . '/' . $f,
|
||||||
|
'items' => $scan($dir . DS . $f), // Recursively get the contents of the folder
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// It is a file
|
||||||
|
|
||||||
|
$files[] = [
|
||||||
|
'name' => $f,
|
||||||
|
'type' => 'file',
|
||||||
|
'path' => str_replace([$scandir, '\\'], ['', '/'], $dir) . '/' . $f,
|
||||||
|
'size' => @filesize($dir . DS . $f), // Gets the size of this file
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
|
};
|
||||||
|
|
||||||
|
$response = $scan($scandir);
|
||||||
|
|
||||||
|
// Output the directory listing as JSON
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output([
|
||||||
|
'name' => '',
|
||||||
|
'type' => 'folder',
|
||||||
|
'path' => '',
|
||||||
|
'items' => $response,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
913
admin/controller/editor/editor.php
Normal file
913
admin/controller/editor/editor.php
Normal file
@ -0,0 +1,913 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Editor;
|
||||||
|
|
||||||
|
use \Vvveb\Sql\menuSQL;
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\getUrl;
|
||||||
|
use function Vvveb\model;
|
||||||
|
use function Vvveb\sanitizeFileName;
|
||||||
|
use function Vvveb\slugify;
|
||||||
|
use Vvveb\Sql\PostSQL;
|
||||||
|
use Vvveb\Sql\ProductSQL;
|
||||||
|
use Vvveb\System\Cache;
|
||||||
|
use Vvveb\System\CacheManager;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\PageCache;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
use function Vvveb\url;
|
||||||
|
|
||||||
|
class Editor extends Base {
|
||||||
|
use GlobalTrait;
|
||||||
|
|
||||||
|
protected $revisionDateFormat = 'Y-m-d_H:i:s';
|
||||||
|
|
||||||
|
private $themeConfig = [];
|
||||||
|
|
||||||
|
private $skipFolders = ['src', 'source', 'backup', 'import'];
|
||||||
|
|
||||||
|
private $skipFiles = [];
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
$return = parent::init();
|
||||||
|
$this->loadThemeConfig();
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function oEmbedProxy() {
|
||||||
|
$url = $this->request->get['url'];
|
||||||
|
|
||||||
|
if (! $url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$result = getUrl($url, false);
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getTheme() {
|
||||||
|
return $theme = sanitizeFileName($this->request->get['theme'] ?? Sites::getTheme($this->global['site_id']) ?? 'default');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getThemeFolder() {
|
||||||
|
return DIR_THEMES . $this->getTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadThemeConfig() {
|
||||||
|
$config = $this->getThemeFolder() . DS . 'theme.php';
|
||||||
|
|
||||||
|
if (file_exists($config)) {
|
||||||
|
$this->themeConfig = include $config;
|
||||||
|
} else {
|
||||||
|
//default config
|
||||||
|
$this->themeConfig = [
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadTemplateList($theme = null) {
|
||||||
|
$list = $this->themeConfig['pages'] ?? [];
|
||||||
|
|
||||||
|
$pages = $list + Cache::getInstance()->cache(APP, 'template-list-' . $theme,
|
||||||
|
function () use ($theme) {
|
||||||
|
return \Vvveb\getTemplateList($theme);
|
||||||
|
}, 604800);
|
||||||
|
|
||||||
|
list($pages) = Event::trigger(__CLASS__, __FUNCTION__, $pages);
|
||||||
|
|
||||||
|
return $pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function clearTemplateListCache($theme = null) {
|
||||||
|
return Cache::getInstance()->delete(APP, 'template-list-' . $theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadEditorData() {
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
//menu list
|
||||||
|
$menuSql = new \Vvveb\Sql\menuSQL();
|
||||||
|
$results = $menuSql->getAll($this->global);
|
||||||
|
|
||||||
|
$data += $results;
|
||||||
|
|
||||||
|
list($data) = Event::trigger(__CLASS__, __FUNCTION__, $data);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load theme sections, components and inputs
|
||||||
|
*/
|
||||||
|
private function loadEditorAssets() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load theme sections, components and inputs
|
||||||
|
*/
|
||||||
|
private function loadThemeAssets() {
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
$view = &$this->view;
|
||||||
|
$themeJs = [];
|
||||||
|
|
||||||
|
foreach (['inputs', 'components', 'blocks', 'sections'] as $type) {
|
||||||
|
$$type = [];
|
||||||
|
$glob = glob("$themeFolder/$type/*.js");
|
||||||
|
|
||||||
|
foreach ($glob as &$file) {
|
||||||
|
$base = str_replace('.js', '', basename($file));
|
||||||
|
$$type[$base] = str_replace($themeFolder, $view->themeBaseUrl, $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list($inputs, $components, $blocks, $sections) =
|
||||||
|
Event::trigger(__CLASS__, __FUNCTION__, $inputs, $components, $blocks, $sections);
|
||||||
|
|
||||||
|
$vvvebJs = '/js/vvvebjs.js';
|
||||||
|
|
||||||
|
if (file_exists($themeFolder . $vvvebJs)) {
|
||||||
|
$themeJs['vvvebjs'] = $view->themeBaseUrl . $vvvebJs;
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->themeInputs = $inputs;
|
||||||
|
$view->themeComponents = $components;
|
||||||
|
$view->themeSections = $sections;
|
||||||
|
$view->themeBlocks = $blocks;
|
||||||
|
$view->themeJs = $themeJs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function proxy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$theme = $this->getTheme();
|
||||||
|
$themeParam = ($theme ? '&theme=' . $theme : '');
|
||||||
|
$view = View::getInstance();
|
||||||
|
$view->themeBaseUrl = PUBLIC_PATH . 'themes/' . $theme . '/';
|
||||||
|
$view->themeName = $theme;
|
||||||
|
$view->pages = $this->loadTemplateList($theme);
|
||||||
|
|
||||||
|
$view->themeFonts = Cache::getInstance()->cache(APP,'fonts-list-' . $theme, function () use ($theme) {
|
||||||
|
$fonts = \Vvveb\System\Media\Font::themeFonts($theme);
|
||||||
|
$names = [];
|
||||||
|
|
||||||
|
if ($fonts) {
|
||||||
|
foreach ($fonts as $font) {
|
||||||
|
if (isset($font['font-family'])) {
|
||||||
|
$names[$font['font-family']] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}, 604800);
|
||||||
|
|
||||||
|
$this->loadThemeAssets();
|
||||||
|
$urlPrefix = '';
|
||||||
|
$urlParams = '';
|
||||||
|
//if admin host is different than site host (for multi site install) use full url including host
|
||||||
|
if ($_SERVER['HTTP_HOST'] !== $this->global['site_url']) {
|
||||||
|
//$urlPrefix = '//' . $this->global['site_url'];
|
||||||
|
$urlParams = '&site_id=' . $this->global['site_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->posts = new PostSQL();
|
||||||
|
$options = [
|
||||||
|
'type' => 'page',
|
||||||
|
'limit' => 100,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $this->posts->getAll($options);
|
||||||
|
$posts = [];
|
||||||
|
|
||||||
|
if ($results && isset($results['post'])) {
|
||||||
|
foreach ($results['post'] as $post) {
|
||||||
|
//skip posts without translations
|
||||||
|
if (! isset($post['slug']) || ! isset($post['name'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$slug = htmlspecialchars($post['slug']);
|
||||||
|
$url = url('content/page/index',['slug' => $slug, 'post_id' => $post['post_id']]);
|
||||||
|
|
||||||
|
$posts["$slug-page"] = [
|
||||||
|
'name' => "$slug-page",
|
||||||
|
'file' => $post['template'] ? $post['template'] : 'content/page.html',
|
||||||
|
'url' => $urlPrefix . $url . ($theme ? '?theme=' . $theme : '') . $urlParams,
|
||||||
|
'title' => htmlspecialchars($post['name']),
|
||||||
|
'post_id' => $post['post_id'],
|
||||||
|
'folder' => '',
|
||||||
|
'className' => 'page',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($posts) {
|
||||||
|
$view->pages = $posts + $view->pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request->get['url'])) {
|
||||||
|
$url = sanitizeFileName($this->request->get['url']);
|
||||||
|
$name = $this->request->get['name'] ?? '';
|
||||||
|
$template = $this->request->get['template'] ?? ''; //\Vvveb\getUrlTemplate($url) ?? 'index.html';
|
||||||
|
$folder = $this->request->get['folder'] ?? false;
|
||||||
|
$route = \Vvveb\getUrlRoute($url);
|
||||||
|
$file = $template;
|
||||||
|
$className = 'url';
|
||||||
|
$current_page = [];
|
||||||
|
|
||||||
|
//check if url and template is relative
|
||||||
|
if (strpos($url, '//') !== false && strpos($template, '..') !== false) {
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if the url has extension and is a html file and exists in the theme folder
|
||||||
|
if (strpos($url, '.') !== false) {
|
||||||
|
if (substr_compare($url, '.html', -5 ,5) === 0) {
|
||||||
|
//check if plugin template exists
|
||||||
|
if (substr_compare($url, '/plugins/', 0 ,9) === 0) {
|
||||||
|
$pluginFile = substr($url, 9);
|
||||||
|
$pluginFile = preg_replace('@^(.+/)@', '$1/public/',$pluginFile);
|
||||||
|
if (! file_exists(DIR_PLUGINS . $pluginFile)) {
|
||||||
|
$this->notFound(sprintf(__('%s does not exist!'), $pluginFile));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//check if theme template exists
|
||||||
|
if (! file_exists(DIR_THEMES . $theme . DS . $url)) {
|
||||||
|
$this->notFound(sprintf(__('%s does not exist!'), $url));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->notFound(sprintf(__('%s does not exist!'), $url));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if template belongs to theme and is a html file
|
||||||
|
if (substr_compare($template, '.html', -5 ,5) === 0) {
|
||||||
|
//check if plugin template exists
|
||||||
|
if (substr_compare($template, '/plugins/', 0 ,9) === 0) {
|
||||||
|
$pluginFile = substr($template, 9);
|
||||||
|
$pluginFile = preg_replace('@^(.+/)@', '$1/public/', $pluginFile);
|
||||||
|
if (! file_exists(DIR_PLUGINS . $pluginFile)) {
|
||||||
|
$this->notFound(sprintf(__('%s does not exist!'), $pluginFile));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//check if theme template exists
|
||||||
|
if (! file_exists(DIR_THEMES . $theme . DS . $template)) {
|
||||||
|
$this->notFound(sprintf(__('%s does not exist!'), $template));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->notFound();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($route && isset($route['module'])) {
|
||||||
|
switch ($route['module']) {
|
||||||
|
case 'product/product/index':
|
||||||
|
$className = 'product';
|
||||||
|
|
||||||
|
if (isset($route['product_id'])) {
|
||||||
|
$current_page['product_id'] = $route['product_id'];
|
||||||
|
} else {
|
||||||
|
if (isset($this->request->get['product_id'])) {
|
||||||
|
$current_page['product_id'] = $this->request->get['product_id'];
|
||||||
|
} else {
|
||||||
|
if (isset($route['slug'])) {
|
||||||
|
$current_page['slug'] = htmlspecialchars($route['slug']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'content/post/index':
|
||||||
|
case 'content/page/index':
|
||||||
|
$className = 'page';
|
||||||
|
|
||||||
|
if (isset($route['post_id'])) {
|
||||||
|
$current_page['post_id'] = $route['post_id'];
|
||||||
|
} else {
|
||||||
|
if (isset($this->request->get['post_id'])) {
|
||||||
|
$current_page['post_id'] = $this->request->get['post_id'];
|
||||||
|
} else {
|
||||||
|
if (isset($route['slug'])) {
|
||||||
|
$current_page['slug'] = htmlspecialchars($route['slug']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = slugify($url);
|
||||||
|
$slug = slugify(str_replace('.html', '', $template));
|
||||||
|
|
||||||
|
if ($url == '/') {
|
||||||
|
$key = $slug = 'index';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $name) {
|
||||||
|
//if in page list get pretty name
|
||||||
|
if (isset($view->pages[$slug])) {
|
||||||
|
$name = $view->pages[$slug]['title'];
|
||||||
|
} else {
|
||||||
|
$name = \Vvveb\humanReadable($url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$global = false;
|
||||||
|
|
||||||
|
if ($file == 'index.html') {
|
||||||
|
$global = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$current_page += [
|
||||||
|
'name' => $key,
|
||||||
|
'file' => $file,
|
||||||
|
'url' => $urlPrefix . $url . ($theme ? '?theme=' . $theme : '') . $urlParams,
|
||||||
|
'title' => $name,
|
||||||
|
'folder' => '',
|
||||||
|
'className' => $className,
|
||||||
|
'global' => $global,
|
||||||
|
];
|
||||||
|
|
||||||
|
$view->pages = [$key => $current_page] + $view->pages;
|
||||||
|
}
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$mediaControllerPath = $admin_path . 'index.php?module=media/media';
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=editor/editor' . $themeParam;
|
||||||
|
$revisionsPath = $admin_path . 'index.php?module=editor/revisions' . $themeParam;
|
||||||
|
$reusablePath = $admin_path . 'index.php?module=editor/reusable' . $themeParam;
|
||||||
|
|
||||||
|
//media endpoints
|
||||||
|
$this->view->scanUrl = "$mediaControllerPath&action=scan";
|
||||||
|
$this->view->uploadUrl = "$mediaControllerPath&action=upload";
|
||||||
|
$this->view->deleteUrl = "$mediaControllerPath&action=delete";
|
||||||
|
$this->view->renameUrl = "$mediaControllerPath&action=rename";
|
||||||
|
|
||||||
|
//editor endpoints
|
||||||
|
$this->view->namespaceUrl = $admin_path . 'index.php?module=editor';
|
||||||
|
$this->view->editorUrl = $controllerPath;
|
||||||
|
$this->view->saveUrl = "$controllerPath&action=save";
|
||||||
|
$this->view->deleteFileUrl = "$controllerPath&action=delete";
|
||||||
|
$this->view->renameFileUrl = "$controllerPath&action=rename";
|
||||||
|
$this->view->saveReusableUrl = "$reusablePath&action=save";
|
||||||
|
$this->view->oEmbedProxyUrl = "$controllerPath&action=oEmbedProxy";
|
||||||
|
|
||||||
|
$this->view->revisionsUrl = "$revisionsPath&action=revisions";
|
||||||
|
$this->view->revisionLoadUrl = "$revisionsPath&action=load";
|
||||||
|
$this->view->revisionDeleteUrl = "$revisionsPath&action=delete";
|
||||||
|
$this->view->linkUrl = $admin_path . 'index.php?module=content/post&action=urlAutocomplete&type=key-value';
|
||||||
|
$view->templates = \Vvveb\getTemplateList($theme);
|
||||||
|
$view->folders = \Vvveb\getThemeFolderList($theme);
|
||||||
|
$view->data = $this->loadEditorData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function backup($page) {
|
||||||
|
$themeFolder = $this->getThemeFolder() . DS;
|
||||||
|
$backupFolder = $themeFolder . 'backup' . DS;
|
||||||
|
$page = str_replace('.html', '', sanitizeFileName($page));
|
||||||
|
$backupName = str_replace(DS, '-', $page) . '@' . str_replace(':',';', date($this->revisionDateFormat)) . '.html';
|
||||||
|
$file = $themeFolder . $page . '.html';
|
||||||
|
|
||||||
|
if (is_dir($backupFolder)) {
|
||||||
|
if (file_exists($file)) {
|
||||||
|
$content = file_get_contents($themeFolder . $page . '.html');
|
||||||
|
|
||||||
|
if (strpos($content, '<base') !== false) {
|
||||||
|
$content = preg_replace('/<base(.*)href=["\'](.*?)["\'](.*?)>/', '<base$1href="../"$3>', $content);
|
||||||
|
} else {
|
||||||
|
$content = str_replace('<head>', "<head>\n<base href=\"../\">\n", $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
return @file_put_contents($backupFolder . $backupName, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function saveElements($elements) {
|
||||||
|
$products = new ProductSQL();
|
||||||
|
$posts = new PostSQL();
|
||||||
|
$components = [];
|
||||||
|
|
||||||
|
foreach ($elements as $element) {
|
||||||
|
$component = $element['component'];
|
||||||
|
$type = $element['type'];
|
||||||
|
$id = $element['id'];
|
||||||
|
$fields = $element['fields'];
|
||||||
|
|
||||||
|
//todo: check and load components from plugins
|
||||||
|
|
||||||
|
$componentName = "\Vvveb\Component\\$component";
|
||||||
|
|
||||||
|
if (! class_exists($componentName)) {
|
||||||
|
include_once DIR_ROOT . "app/component/$component.php";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! isset($components[$component])) {
|
||||||
|
$components[$component] = new $componentName();
|
||||||
|
}
|
||||||
|
|
||||||
|
$components[$component]->editorSave($id, $fields, $type);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
switch ($type) {
|
||||||
|
case 'product':
|
||||||
|
$product_content = [];
|
||||||
|
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
$name = $field['name'];
|
||||||
|
$value = $field['value'];
|
||||||
|
|
||||||
|
if ($name == 'name' || $name == 'content') {
|
||||||
|
$product_content[$name] = $value;
|
||||||
|
} else {
|
||||||
|
$product[$name] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//$product_content['product_id'] = $id;
|
||||||
|
$product_content['language_id'] = 1;
|
||||||
|
|
||||||
|
$product['product_content'][] = $product_content;
|
||||||
|
$result = $products->edit(['product' => $product, 'product_id' => $id]);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'post':
|
||||||
|
$post_content = [];
|
||||||
|
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
$name = $field['name'];
|
||||||
|
$value = $field['value'];
|
||||||
|
|
||||||
|
if ($name == 'name' || $name == 'content') {
|
||||||
|
$post_content[$name] = $value;
|
||||||
|
} else {
|
||||||
|
$post[$name] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//$post['post_content']['post_id'] = $id;
|
||||||
|
$post_content['language_id'] = 1;
|
||||||
|
$post['post_content'][] = $post_content;
|
||||||
|
|
||||||
|
$result = $posts->edit(['post' => $post, 'post_id' => $id]);
|
||||||
|
|
||||||
|
break;
|
||||||
|
} */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
$post_id = $this->request->post['post_id'] ?? false;
|
||||||
|
$file = sanitizeFileName($this->request->post['file'] ?? '');
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
|
||||||
|
if ($post_id) {
|
||||||
|
$type = 'page';
|
||||||
|
|
||||||
|
if ($post_id) {
|
||||||
|
if (is_numeric($post_id)) {
|
||||||
|
$post_id = [$post_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->posts = new PostSQL();
|
||||||
|
$options = [
|
||||||
|
'post_id' => $post_id, 'type' => $type,
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$result = $this->posts->delete($options);
|
||||||
|
|
||||||
|
if ($result && isset($result['post'])) {
|
||||||
|
$message = ['success' => true, 'message' => ucfirst($type) . __(' deleted!')];
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => sprintf(__('Error deleting %s!'), $type)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($file && file_exists($themeFolder . DS . $file)) {
|
||||||
|
if (unlink($themeFolder . DS . $file)) {
|
||||||
|
$message = ['success' => true, 'message' => __('File deleted!')];
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => __('Error deleting file!')];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => __('File does not exist!')];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rename() {
|
||||||
|
$post_id = $this->request->post['post_id'] ?? false;
|
||||||
|
$product_id = $this->request->post['product_id'] ?? false;
|
||||||
|
$file = sanitizeFileName($this->request->post['file']);
|
||||||
|
$newfile = sanitizeFileName($this->request->post['newfile']);
|
||||||
|
$duplicate = $this->request->post['duplicate'] ?? 'false';
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
$name = $this->request->post['name'] ?? $newfile;
|
||||||
|
$theme = $this->getTheme();
|
||||||
|
$dir = dirname($file);
|
||||||
|
|
||||||
|
if ($newfile) {
|
||||||
|
$slug = sanitizeFileName(str_ireplace('.html', '', (basename($newfile))));
|
||||||
|
$newfile = $slug . '.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentFile = $themeFolder . DS . $file;
|
||||||
|
$targetFile = dirname($currentFile) . DS . $newfile; //save in same folder
|
||||||
|
|
||||||
|
$message = ['success' => false, 'message' => __('Error!')];
|
||||||
|
|
||||||
|
if ($post_id || $product_id) {
|
||||||
|
$model = 'post';
|
||||||
|
$type = 'page';
|
||||||
|
$namespace = 'content';
|
||||||
|
$model_id = $post_id;
|
||||||
|
|
||||||
|
if ($product_id) {
|
||||||
|
$model_id = $product_id;
|
||||||
|
$namespace = 'product';
|
||||||
|
$model = 'product';
|
||||||
|
$type = 'product';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newfile) {
|
||||||
|
$name = sanitizeFileName($this->request->post['name']);
|
||||||
|
$slug = slugify($name);
|
||||||
|
|
||||||
|
$this->posts = model($model);
|
||||||
|
|
||||||
|
if ($duplicate === 'true') {
|
||||||
|
$data = $this->posts->get([$model . '_id' => $model_id]);
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
unset($data[$model . '_id']);
|
||||||
|
$id = rand(1, 1000);
|
||||||
|
|
||||||
|
foreach ($data[$model . '_content'] as &$content) {
|
||||||
|
unset($content[$model . '_id']);
|
||||||
|
|
||||||
|
if ($content['language_id'] == $this->global['language_id']) {
|
||||||
|
$content['name'] = $name;
|
||||||
|
$content['slug'] = $slug;
|
||||||
|
} else {
|
||||||
|
$content['name'] .= ' [' . __('duplicate') . ']';
|
||||||
|
$content['slug'] .= '-' . __('duplicate') . "-$id";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data[$model . '_to_taxonomy_item'])) {
|
||||||
|
foreach ($data[$model . '_to_taxonomy_item'] as &$item) {
|
||||||
|
$taxonomy_item[] = $item['taxonomy_item_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data[$model . '_to_site'])) {
|
||||||
|
foreach ($data[$model . '_to_site'] as &$item) {
|
||||||
|
$site_id[] = $item['site_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$startTemplateUrl = $data['template'] ?? "$namespace/$type.html";
|
||||||
|
$template = "$namespace/$slug.html";
|
||||||
|
|
||||||
|
if (! @copy($themeFolder . DS . $startTemplateUrl, $themeFolder . DS . $template)) {
|
||||||
|
$template = $data['template'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$new = [
|
||||||
|
$model => [
|
||||||
|
'taxonomy_item' => $taxonomy_item ?? [],
|
||||||
|
'template' => $template,
|
||||||
|
] + $data,
|
||||||
|
$model . '_content' => $data[$model . '_content'],
|
||||||
|
'site_id' => $site_id,
|
||||||
|
] + $data + $this->global;
|
||||||
|
|
||||||
|
$result = $this->posts->add($new);
|
||||||
|
|
||||||
|
$newfile = PUBLIC_PATH . "themes/$theme/" . ($dir ? $dir . '/' : '') . $template;
|
||||||
|
|
||||||
|
if ($result && isset($result[$model])) {
|
||||||
|
$model_id = $result[$model];
|
||||||
|
$message = ['success' => true, 'name' => $name, 'slug' => $slug, $model . '_id' => $model_id, 'newfile' => $newfile, 'url' => url("$namespace/$type/index", ['slug' => $slug, $model . '_id' => $model_id]), 'message' => ucfirst($type) . ' ' . __('duplicated') . '!'];
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => sprintf(__('Error duplicating %s!'), $type)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$data = [
|
||||||
|
$model . '_content' => ['name' => $name, 'slug' => $slug],
|
||||||
|
$model . '_id' => $model_id,
|
||||||
|
'language_id' => $this->global['language_id'],
|
||||||
|
];
|
||||||
|
$result = $this->posts->editContent($data);
|
||||||
|
|
||||||
|
$newfile = PUBLIC_PATH . "themes/$theme/" . ($dir ? $dir . '/' : '') . $newfile;
|
||||||
|
|
||||||
|
if ($result && isset($result[$model . '_content'])) {
|
||||||
|
$message = ['success' => true, 'name' => $name, 'slug' => $slug, $model . '_id' => $model_id, 'newfile' => $newfile, 'url' => url("$namespace/$type/index", ['slug' => $slug, $model . '_id' => $model_id]), 'message' => ucfirst($type) . ' ' . __('renamed') . '!'];
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => sprintf(__('Error renaming %s!'), $type)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$newfile = PUBLIC_PATH . "themes/$theme/" . ($dir ? $dir . '/' : '') . $newfile;
|
||||||
|
|
||||||
|
if ($duplicate === 'true') {
|
||||||
|
if (@copy($currentFile, $targetFile)) {
|
||||||
|
$message = ['success' => true, 'newfile' => $newfile, 'name' => $name, 'message' => __('File copied!'), 'url' => $newfile];
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => __('Error copying file!')];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rename($currentFile, $targetFile)) {
|
||||||
|
$message = ['success' => true, 'newfile' => $newfile, 'name' => $name, 'message' => __('File renamed!')];
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => __('Error renaming file!')];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->clearTemplateListCache(sanitizeFileName($this->request->get['theme'] ?? false));
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$file = $this->request->post['file'] ?? '';
|
||||||
|
$folder = $this->request->post['folder'] ?? '';
|
||||||
|
$startTemplateUrl = $this->request->post['startTemplateUrl'] ?? '';
|
||||||
|
$name = $this->request->post['name'] ?? '';
|
||||||
|
$content = $this->request->post['content'] ?? 'Lorem ipsum';
|
||||||
|
$image = $this->request->post['image'] ?? '';
|
||||||
|
$type = $this->request->post['type'] ?? false;
|
||||||
|
$templateType = $this->request->post['template-type'] ?? false;
|
||||||
|
$addMenu = $this->request->post['add-menu'] ?? false;
|
||||||
|
$menu_id = $this->request->post['menu_id'] ?? false;
|
||||||
|
$uri = $this->request->post['url'] ?? '/';
|
||||||
|
$theme = $this->getTheme();
|
||||||
|
$url = '';
|
||||||
|
|
||||||
|
$file = sanitizeFileName(str_replace('.html', '', $file)) . '.html';
|
||||||
|
$folder = trim(sanitizeFileName($folder), '/');
|
||||||
|
$startTemplateUrl = sanitizeFileName($startTemplateUrl);
|
||||||
|
|
||||||
|
if ($type && $name) {
|
||||||
|
$slug = slugify($name);
|
||||||
|
$success = false;
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'page':
|
||||||
|
case 'post':
|
||||||
|
$file = $templateType == 'global' ? "content/$type.html" : "content/$slug.html";
|
||||||
|
$file = sanitizeFileName($file);
|
||||||
|
$template = $templateType == 'global' && $startTemplateUrl ? $startTemplateUrl : $file;
|
||||||
|
$post = new PostSQL();
|
||||||
|
$result = $post->add([
|
||||||
|
'post' => [
|
||||||
|
'template' => $template,
|
||||||
|
'type' => $type,
|
||||||
|
'image' => $image,
|
||||||
|
] + $this->global,
|
||||||
|
'post_content' => [[
|
||||||
|
'slug' => $slug,
|
||||||
|
'name' => $name,
|
||||||
|
'content' => $content,
|
||||||
|
'language_id' => $this->global['language_id'],
|
||||||
|
]],
|
||||||
|
'site_id' => [$this->global['site_id']],
|
||||||
|
] + $this->global);
|
||||||
|
|
||||||
|
if ($result['post']) {
|
||||||
|
$post_id = $result['post'];
|
||||||
|
$success = true;
|
||||||
|
$route = "content/{$type}/index";
|
||||||
|
$url = \Vvveb\url($route, ['slug'=> $slug, 'post_id'=> $post_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'product':
|
||||||
|
$file = $templateType == 'global' ? "product/$type.html" : "product/$slug.html";
|
||||||
|
$file = sanitizeFileName($file);
|
||||||
|
$template = $templateType == 'global' && $startTemplateUrl ? $startTemplateUrl : $file;
|
||||||
|
$price = $this->request->post['price'] ?? 0;
|
||||||
|
$product = new ProductSQL();
|
||||||
|
$result = $product->add([
|
||||||
|
'product' => [
|
||||||
|
'model' => '',
|
||||||
|
'image' => $image,
|
||||||
|
'status' => 1, //active
|
||||||
|
'template' => $file,
|
||||||
|
'price' => $price,
|
||||||
|
] + $this->global,
|
||||||
|
'product_content' => [[
|
||||||
|
'slug' => $slug,
|
||||||
|
'name' => $name,
|
||||||
|
'name' => $name,
|
||||||
|
'content' => $content,
|
||||||
|
'language_id' => $this->global['language_id'],
|
||||||
|
]],
|
||||||
|
'site_id' => [$this->global['site_id']], ] + $this->global);
|
||||||
|
|
||||||
|
if ($result['product']) {
|
||||||
|
$product_id = $result['product'];
|
||||||
|
$success = true;
|
||||||
|
$route = "product/{$type}/index";
|
||||||
|
$url = \Vvveb\url($route, ['slug' => $slug, 'product_id'=> $product_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = $this->request->post['html'] ?? false;
|
||||||
|
$elements = $this->request->post['elements'] ?? false;
|
||||||
|
$setTemplate = $this->request->post['setTemplate'] ?? false;
|
||||||
|
|
||||||
|
$view = View::getInstance();
|
||||||
|
$view->noJson = true;
|
||||||
|
$success = false;
|
||||||
|
$text = '';
|
||||||
|
|
||||||
|
$baseUrl = PUBLIC_PATH . 'themes/' . $theme . '/' . ($folder ? $folder . '/' : '');
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
$relativeBase = '';
|
||||||
|
$pos = 0;
|
||||||
|
|
||||||
|
//if more than one level deep add one level up for each level
|
||||||
|
$fileBase = ($folder ? $folder . '/' : '') . $file;
|
||||||
|
while (($pos = strpos($fileBase, '/', $pos + 1)) !== false) {
|
||||||
|
$relativeBase .= '../';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($startTemplateUrl) {
|
||||||
|
$startTemplate = $themeFolder . DS . $startTemplateUrl;
|
||||||
|
|
||||||
|
if (file_exists($startTemplate)) {
|
||||||
|
if (! ($html = @file_get_contents($startTemplate))) {
|
||||||
|
$text .= sprintf(__('%s is not readable!'), $startTemplate);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$text .= sprintf(__('%s does not exist!'), $startTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = preg_replace('@<base\s+href[^>]+>@', '<base href="' . $relativeBase . '">', $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $url) {
|
||||||
|
$url = "$baseUrl$file";
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = compact('file', 'name', 'url', 'startTemplateUrl');
|
||||||
|
|
||||||
|
if ($elements) {
|
||||||
|
if ($this->saveElements($elements)) {
|
||||||
|
$success = true;
|
||||||
|
$text = __('Elements saved!') . "\n";
|
||||||
|
} else {
|
||||||
|
$success = false;
|
||||||
|
$text = __('Error saving elements!') . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if plugins template use public path
|
||||||
|
$isPlugin = false;
|
||||||
|
|
||||||
|
if (strncmp($file, '/plugins/', 9) === 0) {
|
||||||
|
$pluginFile = substr($file, 9);
|
||||||
|
$pluginFile = preg_replace('@^(.+/)@', '$1/public/', $pluginFile);
|
||||||
|
$fileName = DIR_PLUGINS . /*($folder ? $folder . DS : '') .*/ $pluginFile;
|
||||||
|
$isPlugin = true;
|
||||||
|
} else {
|
||||||
|
$fileName = $themeFolder . DS . ($folder ? $folder . DS : '') . $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $startTemplateUrl && ! $isPlugin) {
|
||||||
|
$backupFolder = $themeFolder . DS . 'backup' . DS;
|
||||||
|
|
||||||
|
if (is_writable($backupFolder)) {
|
||||||
|
if ($this->backup($file)) {
|
||||||
|
} else {
|
||||||
|
$success = false;
|
||||||
|
$text .= __('Error saving revision!') . "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$success = false;
|
||||||
|
$text .= sprintf(__('%s folder not writable!'), $theme . DS . 'backup') . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($addMenu && $menu_id) {
|
||||||
|
$menuData = ['menu_item' => [
|
||||||
|
'menu_id' => $menu_id,
|
||||||
|
'url' => $url,
|
||||||
|
'menu_item_content' => [[
|
||||||
|
'name' => $name,
|
||||||
|
'slug' => $slug,
|
||||||
|
'language_id' => $this->global['language_id'],
|
||||||
|
'content' => '',
|
||||||
|
]],
|
||||||
|
]] + $this->global;
|
||||||
|
|
||||||
|
$menus = new menuSQL();
|
||||||
|
$results = $menus->addMenuItem($menuData);
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
$text .= "\n" . __('Menu item added!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($html) {
|
||||||
|
//reset base href so that html file can be loaded properly in browser directly from folder
|
||||||
|
//$html = preg_replace('@<base href[^>]+>@', '', $html);
|
||||||
|
$html = preg_replace('@<base href[^>]+>@', '<base href="' . $relativeBase . '">', $html);
|
||||||
|
//remove empty value for data attributes
|
||||||
|
$html = preg_replace('/(data-[\w\-]+)="\s*"/','$1', $html);
|
||||||
|
|
||||||
|
if (@file_put_contents($fileName, $html)) {
|
||||||
|
$globalOptions = [];
|
||||||
|
//keep css inline for email templates
|
||||||
|
if (strpos($fileName, '/email/') !== false) {
|
||||||
|
$globalOptions['inline-css'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = $this->saveGlobalElements($html, $globalOptions);
|
||||||
|
|
||||||
|
$success = true;
|
||||||
|
$text .= __('File saved!');
|
||||||
|
} else {
|
||||||
|
if (! is_writable($fileName)) {
|
||||||
|
$text .= sprintf(__('%s is not writable!'), $file);
|
||||||
|
} else {
|
||||||
|
$text .= sprintf(__('Error saving %s!'), $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$text .= __('Page html empty!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$cssFile = DS . 'css' . DS . 'custom.css';
|
||||||
|
|
||||||
|
//try to create custom.css if it doesn't exist
|
||||||
|
if (! file_exists($themeFolder . $cssFile) && ! touch($themeFolder . $cssFile)) {
|
||||||
|
$text .= '<br/>' . sprintf(__('Can not create file %s!'), $theme . $cssFile);
|
||||||
|
} else {
|
||||||
|
if (! is_writable($themeFolder . $cssFile)) {
|
||||||
|
$text .= '<br/>' . sprintf(__('%s is not writable!'), $theme . $cssFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CacheManager::clearCompiledFiles('app', $this->global['site_id'], $theme)) {
|
||||||
|
$pageCache = new PageCache();
|
||||||
|
$uri = preg_replace('/\?.+/', '', $uri);
|
||||||
|
$path = $pageCache->uri($uri);
|
||||||
|
$pageCache->purge($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data += ['success' => $success, 'message' => $text];
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
135
admin/controller/editor/global-trait.php
Normal file
135
admin/controller/editor/global-trait.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Editor;
|
||||||
|
|
||||||
|
trait GlobalTrait {
|
||||||
|
private function saveGlobalElements($content, $options = []) {
|
||||||
|
$document = new \DomDocument();
|
||||||
|
$document->preserveWhiteSpace = true;
|
||||||
|
$document->recover = true;
|
||||||
|
$document->strictErrorChecking = false;
|
||||||
|
$document->substituteEntities = false;
|
||||||
|
$document->formatOutput = false;
|
||||||
|
$document->resolveExternals = false;
|
||||||
|
$document->validateOnParse = false;
|
||||||
|
$document->xmlStandalone = true;
|
||||||
|
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
|
||||||
|
@$document->loadHTML($content);
|
||||||
|
|
||||||
|
$xpath = new \DOMXpath($document);
|
||||||
|
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
|
||||||
|
if (! isset($options['inline-css']) || $options['inline-css'] == false) {
|
||||||
|
//save vvvebjs css to custom.css
|
||||||
|
$style = $xpath->query('//style[ @id="vvvebjs-styles" ]');
|
||||||
|
$cssFile = $themeFolder . DS . 'css' . DS . 'custom.css';
|
||||||
|
|
||||||
|
if ($style && $style->length && is_writable($cssFile)) {
|
||||||
|
$element = $style[0];
|
||||||
|
$content = trim($element->nodeValue);
|
||||||
|
|
||||||
|
if ($content && file_put_contents($cssFile, $element->nodeValue)) {
|
||||||
|
$link = $document->createElement('link');
|
||||||
|
$link->setAttribute('href', 'css/custom.css');
|
||||||
|
$link->setAttribute('rel', 'stylesheet');
|
||||||
|
$link->setAttribute('media', 'screen');
|
||||||
|
$link->setAttribute('id', 'vvvebjs-css');
|
||||||
|
$element->parentNode->replaceChild($link, $element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//save common global elements like footer/header
|
||||||
|
$elements = $xpath->query('//*[ @data-v-save-global ]');
|
||||||
|
|
||||||
|
if ($elements && $elements->length) {
|
||||||
|
$toDocument = new \DomDocument();
|
||||||
|
$toDocument->preserveWhiteSpace = false;
|
||||||
|
$toDocument->recover = true;
|
||||||
|
$toDocument->strictErrorChecking = false;
|
||||||
|
$toDocument->formatOutput = false;
|
||||||
|
$toDocument->resolveExternals = false;
|
||||||
|
$toDocument->validateOnParse = false;
|
||||||
|
$toDocument->xmlStandalone = true;
|
||||||
|
|
||||||
|
foreach ($elements as $element) {
|
||||||
|
if (! $element->hasChildNodes()) {
|
||||||
|
continue;
|
||||||
|
}//skip empty elements
|
||||||
|
|
||||||
|
$attribute = $element->getAttribute('data-v-save-global');
|
||||||
|
|
||||||
|
if (strpos($attribute, ',') !== false) {
|
||||||
|
list($file, $selector) = explode(',', $attribute);
|
||||||
|
|
||||||
|
$file = html_entity_decode($file);
|
||||||
|
$selector = html_entity_decode($selector);
|
||||||
|
$file = $themeFolder . DS . $file;
|
||||||
|
|
||||||
|
$toDocument->loadHTMLFile($file);
|
||||||
|
|
||||||
|
$toXpath = new \DOMXpath($toDocument);
|
||||||
|
|
||||||
|
$toElements = $toXpath->query(\Vvveb\cssToXpath($selector));
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
if ($elements && $elements->length) {
|
||||||
|
foreach ($toElements as $externalNode) {
|
||||||
|
$parent = $externalNode->parentNode;
|
||||||
|
|
||||||
|
$importedNode = $toDocument->importNode($element, true);
|
||||||
|
|
||||||
|
if ($parent) {
|
||||||
|
/*
|
||||||
|
if ($count) {
|
||||||
|
$parent->appendChild($importedNode);
|
||||||
|
} else {
|
||||||
|
$parent->replaceChild($importedNode, $externalNode);
|
||||||
|
}*/
|
||||||
|
$parent->replaceChild($importedNode, $externalNode);
|
||||||
|
$externalNode = $importedNode;
|
||||||
|
$parent = $externalNode->parentNode;
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = $toDocument->saveHTML();
|
||||||
|
|
||||||
|
if (is_writable($file)) {
|
||||||
|
if (@file_put_contents($file, $html)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$content= $document->saveHTML();
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
133
admin/controller/editor/reusable.php
Normal file
133
admin/controller/editor/reusable.php
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Editor;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use function Vvveb\sanitizeFileName;
|
||||||
|
use function Vvveb\slugify;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
|
||||||
|
class Reusable extends Base {
|
||||||
|
private $sectionTemplate = <<<TPL
|
||||||
|
|
||||||
|
Vvveb.Sections.add("reusable/{name}", {
|
||||||
|
name: "{title}",
|
||||||
|
//image: Vvveb.themeBaseUrl + "/../../media/img/logo-small.png",
|
||||||
|
image: "img/logo-small.png",
|
||||||
|
html: `{content}`
|
||||||
|
});
|
||||||
|
Vvveb.SectionsGroup['Reusable'].push("reusable/{name}");
|
||||||
|
|
||||||
|
TPL;
|
||||||
|
|
||||||
|
private $blockTemplate = <<<TPL
|
||||||
|
|
||||||
|
Vvveb.Blocks.add("reusable/{name}", {
|
||||||
|
name: "{title}",
|
||||||
|
//image: Vvveb.themeBaseUrl + "/../../media/img/logo-small.png",
|
||||||
|
image: "img/logo-small.png",
|
||||||
|
html: `{content}`
|
||||||
|
});
|
||||||
|
Vvveb.BlocksGroup['Reusable'].push("reusable/{name}");
|
||||||
|
|
||||||
|
TPL;
|
||||||
|
|
||||||
|
private function getThemeFolder() {
|
||||||
|
return DIR_THEMES . ($this->request->get['theme'] ?? Sites::getTheme(SITE_ID) ?? 'default');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function regenerate($type) {
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
|
||||||
|
$folder = $themeFolder . DS . $type . 's' . DS;
|
||||||
|
$htmlFolder = $folder . 'reusable' . DS;
|
||||||
|
$template = ($type == 'section') ? $this->sectionTemplate : $this->blockTemplate;
|
||||||
|
|
||||||
|
$js = '';
|
||||||
|
|
||||||
|
foreach (scandir($htmlFolder) as $file) {
|
||||||
|
if (strpos($file, '.html') === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$name = str_replace('.html','', $file);
|
||||||
|
$title = humanReadable($name);
|
||||||
|
$content = file_get_contents($htmlFolder . DS . $file);
|
||||||
|
|
||||||
|
$data = compact('name', 'title', 'content');
|
||||||
|
$reusable = $template;
|
||||||
|
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
$reusable = str_replace('{' . $key . '}', $value, $reusable);
|
||||||
|
}
|
||||||
|
|
||||||
|
$js .= $reusable;
|
||||||
|
}
|
||||||
|
|
||||||
|
$jsFile = $folder . $type . 's.js';
|
||||||
|
$typeName = ucfirst($type);
|
||||||
|
$jsContent = '';
|
||||||
|
|
||||||
|
if (file_exists($jsFile)) {
|
||||||
|
$jsContent = file_get_contents($jsFile);
|
||||||
|
|
||||||
|
//remove old reusable
|
||||||
|
$regex = '\s*Vvveb\.\w+?\.add\([\'"]reusable.+?`\s*\}\);?|' .
|
||||||
|
'\s*Vvveb\.\w+?Group\[["\']Reusable["\']\]\s*\.push\([^\)]+\);?\s*|' .
|
||||||
|
'\s*Vvveb\.\w+?Group\[["\']Reusable["\']\]\s*=\s*\[[^\]]*?\];?\s*';
|
||||||
|
|
||||||
|
$jsContent = preg_replace("/$regex/ms", '', $jsContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//append new reusable
|
||||||
|
$jsContent = $jsContent . "\n\nVvveb." . $typeName . "sGroup[\"Reusable\"] = [];\n" . $js;
|
||||||
|
|
||||||
|
return file_put_contents($jsFile, $jsContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$name = slugify(sanitizeFileName($this->request->post['name']));
|
||||||
|
$type = $this->request->post['type'];
|
||||||
|
$html = $this->request->post['html'];
|
||||||
|
$message = ['success' => false, 'message' => __('Error saving!')];
|
||||||
|
|
||||||
|
if (($type == 'section' || $type == 'block') && $html) {
|
||||||
|
$themeFolder = $this->getThemeFolder();
|
||||||
|
$folder = $themeFolder . DS . $type . 's' . DS . 'reusable' . DS;
|
||||||
|
$file = "$name.html";
|
||||||
|
|
||||||
|
@mkdir($folder, 0755 & ~umask(), true);
|
||||||
|
|
||||||
|
if (file_put_contents($folder . $file, $html)) {
|
||||||
|
if ($this->regenerate($type)) {
|
||||||
|
$message = ['success' => true, 'message' => __('Element saved!')];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($message);
|
||||||
|
}
|
||||||
|
}
|
||||||
133
admin/controller/editor/revisions.php
Normal file
133
admin/controller/editor/revisions.php
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Editor;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\friendlyDate;
|
||||||
|
use function Vvveb\sanitizeFileName;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
|
||||||
|
class Revisions extends Base {
|
||||||
|
function getThemeFolder() {
|
||||||
|
$theme = $this->request->get['theme'] ?? Sites::getTheme(SITE_ID) ?? 'default';
|
||||||
|
|
||||||
|
return $theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sanitizeBackupFileName($fileName) {
|
||||||
|
return str_replace(['.', '/', '\\'], '', $fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function backupFolder() {
|
||||||
|
$theme = $this->getThemeFolder();
|
||||||
|
|
||||||
|
return DIR_THEMES . $theme . DS . 'backup' . DS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
$file = $this->request->post['file'] ?? false;
|
||||||
|
|
||||||
|
if ($file) {
|
||||||
|
$file = $this->backupFolder() . $this->sanitizeBackupFileName($file) . '.html';
|
||||||
|
|
||||||
|
$text = __('Error deleting file!' . $file);
|
||||||
|
$success = false;
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
$success = unlink($file);
|
||||||
|
|
||||||
|
if ($success) {
|
||||||
|
$text = __('File deleted!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = ['success' => $success, 'message' => $text];
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
$file = $this->request->post['file'] ?? false;
|
||||||
|
$theme = $this->getThemeFolder();
|
||||||
|
|
||||||
|
if ($file) {
|
||||||
|
$file = $this->backupFolder() . $this->sanitizeBackupFileName($file) . '.html';
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
$this->response->setType('text');
|
||||||
|
$html = file_get_contents($file);
|
||||||
|
$base = "/themes/$theme/";
|
||||||
|
|
||||||
|
if (strpos($html, '<base') !== false) {
|
||||||
|
$html = preg_replace('/<base(.*)href=["\'](.*?)["\'](.*?)>/', '<base$1href="' . $base . '"$3>', $html);
|
||||||
|
} else {
|
||||||
|
$html = str_replace('<head>', "<head>\n<base href=\"$base\">\n", $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->output($html);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die(__('Invalid request!'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function revisions() {
|
||||||
|
$theme = $this->getThemeFolder();
|
||||||
|
$template = $this->request->get['template'] ?? false;
|
||||||
|
$backupFolder = $this->backupFolder();
|
||||||
|
$revisions = [];
|
||||||
|
|
||||||
|
if ($template) {
|
||||||
|
$templateName = str_replace(['/', '.html'], ['-', ''], sanitizeFileName($template));
|
||||||
|
$path = '//' . $_SERVER['HTTP_HOST'] . PUBLIC_PATH . "/themes/$theme/";
|
||||||
|
|
||||||
|
$glob = glob("$backupFolder/$templateName@*.html");
|
||||||
|
|
||||||
|
foreach ($glob as &$file) {
|
||||||
|
$file = basename($file, '.html');
|
||||||
|
$url = $path . "backup/$file.html";
|
||||||
|
list($name, $date) = explode('@', $file);
|
||||||
|
$date = str_replace(['_', ';'], [' ', ':'], $date);
|
||||||
|
$date_friendly = friendlyDate($date);
|
||||||
|
/*
|
||||||
|
$time = date_parse_from_format($this->revisionDateFormat, $date);
|
||||||
|
unset($time['warnings'], $time['warning_count'], $time['errors'], $time['error_count']);
|
||||||
|
*/
|
||||||
|
$revisions[$date] = compact(['url', 'file', 'date', 'date_friendly', 'name'/*, 'time'*/]);
|
||||||
|
}
|
||||||
|
|
||||||
|
krsort($revisions);
|
||||||
|
|
||||||
|
//$revisions[0] = ['url' => $path . $template, 'file' => $template, '' => '', 'date_friendly' => 'Live', 'date' => '', 'name' => ''];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($revisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
}
|
||||||
|
}
|
||||||
103
admin/controller/editor/translate.php
Normal file
103
admin/controller/editor/translate.php
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Editor;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
|
||||||
|
class Translate extends Base {
|
||||||
|
function get() {
|
||||||
|
$text = $this->request->post['text'];
|
||||||
|
$languages = \Vvveb\availableLanguages();
|
||||||
|
$translations = [];
|
||||||
|
|
||||||
|
foreach ($languages as $lang) {
|
||||||
|
$code = $lang['code'];
|
||||||
|
\Vvveb\setLanguage($code);
|
||||||
|
$translations[$code] = __($text);
|
||||||
|
}
|
||||||
|
//restore language
|
||||||
|
\Vvveb\setLanguage(\Vvveb\getLanguage());
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($translations);
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$translations = $this->request->post ?? [];
|
||||||
|
$success = true;
|
||||||
|
$message = __('Translations saved!');
|
||||||
|
|
||||||
|
if ($translations) {
|
||||||
|
require_once DIR_SYSTEM . 'functions' . DS . 'php-mo.php';
|
||||||
|
unset($translations['csrf']);
|
||||||
|
|
||||||
|
$defaultLang = key($translations); //'en_US';
|
||||||
|
$domain = 'vvveb';
|
||||||
|
$text = $translations[$defaultLang];
|
||||||
|
|
||||||
|
foreach ($translations as $langCode => $translation) {
|
||||||
|
if ($langCode == $defaultLang || $langCode == 'en_US' || $success == false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$folder = DIR_ROOT . 'locale' . DS . $langCode . DS . 'LC_MESSAGES' . DS;
|
||||||
|
$userpoFile = $folder . 'user.po';
|
||||||
|
$poFile = $folder . $domain . '.po';
|
||||||
|
$moFile = $folder . $domain . '.mo';
|
||||||
|
|
||||||
|
foreach ([$poFile, $moFile] as $file) {
|
||||||
|
if (! is_writable($file)) {
|
||||||
|
$message = sprintf(__('File %s not writable!'), $file);
|
||||||
|
$success = false;
|
||||||
|
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$userTranslations = [];
|
||||||
|
|
||||||
|
if (file_exists($userpoFile)) {
|
||||||
|
$userTranslations = phpmo_parse_po_file($userpoFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
$userTranslations[$text] = ['msgid' => $text, 'msgstr' => [$translation]];
|
||||||
|
|
||||||
|
if (phpmo_write_po_file($userTranslations, $userpoFile)) {
|
||||||
|
$userTranslations += phpmo_parse_po_file($poFile);
|
||||||
|
|
||||||
|
if (phpmo_write_mo_file($userTranslations, $moFile)) {
|
||||||
|
} else {
|
||||||
|
$message .= __('Error compiling!');
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message = sprintf(__('Error saving %s file!'), $poFile);
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output(['success' => $success, 'message' => $message]);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
admin/controller/error403.php
Normal file
28
admin/controller/error403.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller;
|
||||||
|
|
||||||
|
class Error403 extends Base {
|
||||||
|
function index() {
|
||||||
|
}
|
||||||
|
}
|
||||||
29
admin/controller/error404.php
Normal file
29
admin/controller/error404.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller;
|
||||||
|
|
||||||
|
#[\AllowDynamicProperties]
|
||||||
|
class Error404 {/* extends Base */
|
||||||
|
function index() {
|
||||||
|
}
|
||||||
|
}
|
||||||
29
admin/controller/error500.php
Normal file
29
admin/controller/error500.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller;
|
||||||
|
|
||||||
|
#[\AllowDynamicProperties]
|
||||||
|
class Error500 { /*extends Base */
|
||||||
|
function index() {
|
||||||
|
}
|
||||||
|
}
|
||||||
226
admin/controller/field/field-group.php
Normal file
226
admin/controller/field/field-group.php
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Field;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use function Vvveb\fieldTypeClass;
|
||||||
|
use function Vvveb\getFieldTypes;
|
||||||
|
use function Vvveb\importHtml;
|
||||||
|
use function Vvveb\postTypes;
|
||||||
|
use Vvveb\Sql\Field_GroupSQL;
|
||||||
|
use Vvveb\Sql\FieldSQL;
|
||||||
|
use Vvveb\System\Event;
|
||||||
|
use Vvveb\System\Field as Fields;
|
||||||
|
use Vvveb\System\Traits\FieldGroup as FieldGroupTrait;
|
||||||
|
|
||||||
|
class FieldGroup extends Crud {
|
||||||
|
use FieldGroupTrait;
|
||||||
|
|
||||||
|
protected $type = 'field_group';
|
||||||
|
|
||||||
|
protected $controller = 'field-group';
|
||||||
|
|
||||||
|
protected $module = 'field';
|
||||||
|
|
||||||
|
function setFieldDefault(&$field) {
|
||||||
|
$fieldClass = fieldTypeClass($field['type']);
|
||||||
|
|
||||||
|
if ($fieldClass && $fieldClass::valueType) {
|
||||||
|
$field['default'] = [];
|
||||||
|
|
||||||
|
foreach ($fieldClass::valueType as $key) {
|
||||||
|
$field['default'][$key] = $field['settings'][$key] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$field['default'] = json_encode($field['default']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {/*
|
||||||
|
$field = $this->request->post['field'] ?? [];
|
||||||
|
$field_group_id = $this->request->get['field_group_id'] ?? false;
|
||||||
|
|
||||||
|
if ($field_group_id) {
|
||||||
|
$fieldGroup = new Field_GroupSQL();
|
||||||
|
$result = $fieldGroup->addFields(['field_group_id' => $field_group_id, 'field_to_field_group' => $field]);
|
||||||
|
|
||||||
|
if ($result && isset($result['field_to_field_group'])) {
|
||||||
|
$successMessage = __('Field saved!');
|
||||||
|
$this->view->success[] = $successMessage;
|
||||||
|
$this->view->errors = [];
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
$this->request->post[$this->type]['status'] = 1;
|
||||||
|
$this->redirect = false;
|
||||||
|
parent::save();
|
||||||
|
|
||||||
|
$delete = $this->request->post['delete']['field_id'] ?? [];
|
||||||
|
$field = $this->request->post['field'] ?? [];
|
||||||
|
$field_group = $this->request->post['field_group'] ?? [];
|
||||||
|
$field_group_id = $this->request->get['field_group_id'] ?? false;
|
||||||
|
$edit = $this->request->get['field_group_id'] ?? false;
|
||||||
|
$field_group_id = $this->field_group_id;
|
||||||
|
$new = [];
|
||||||
|
unset($field_group['conditionals']);
|
||||||
|
//var_dump($field);
|
||||||
|
foreach ($field as $index => &$attr) {
|
||||||
|
$attr['field_group_id'] = $field_group_id;
|
||||||
|
$attr['sort_order'] = $attr['sort_order'] ?? 0;
|
||||||
|
|
||||||
|
if ($index === '#') {
|
||||||
|
unset($field[$index]);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attr['name'] = $attr['name'] ?? $attr['settings']['name'] ?? '(none)';
|
||||||
|
$attr['label'] = $attr['label'] ?? $attr['settings']['label'] ?? '(none)';
|
||||||
|
$attr['default'] = $attr['label'] ?? $attr['settings']['default'] ?? '';
|
||||||
|
$attr['type'] = $attr['settings']['type'] ?? 'text';
|
||||||
|
$attr['field_id'] = $attr['settings']['field_id'] ?? $attr['field_id'] ?? null;
|
||||||
|
$attr['sort_order'] = $attr['settings']['sort_order'] ?? $attr['sort_order'] ?? 0;
|
||||||
|
$attr['row'] = $attr['settings']['row'] ?? $attr['row'] ?? 0;
|
||||||
|
|
||||||
|
if (! $attr['name']) {
|
||||||
|
unset($field[$index]);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setFieldDefault($attr);
|
||||||
|
|
||||||
|
foreach (['settings', 'validation', 'presentation', 'conditionals'] as $section) {
|
||||||
|
$attr[$section] = $attr[$section] ?? [];
|
||||||
|
$attr[$section] = array_filter($attr[$section]);
|
||||||
|
$attr[$section] = json_encode($attr[$section]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ($attr['field_id'] ?? false) && $attr['name']) {
|
||||||
|
unset($attr['field_id']);
|
||||||
|
$new[] = $attr;
|
||||||
|
unset($field[$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field_group_id) {
|
||||||
|
$fieldGroup = new Field_GroupSQL();
|
||||||
|
$fieldSql = new FieldSQL();
|
||||||
|
|
||||||
|
if ($delete) {
|
||||||
|
$fieldSql->delete(['field_id' => $delete] + $this->global);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field) {
|
||||||
|
foreach ($field as $index => &$attr) {
|
||||||
|
$fieldSql->edit(['field' => $attr, 'field_id' => $attr['field_id']] + $this->global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($new) {
|
||||||
|
foreach ($new as $index => &$attr) {
|
||||||
|
$fieldSql->add(['field' => $attr] + $this->global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $fieldGroup->edit(['field_group_id' => $field_group_id, 'field_group' => $field_group]);
|
||||||
|
|
||||||
|
if ($result && isset($result['field_group_content'])) {
|
||||||
|
if (! $edit) {
|
||||||
|
$this->redirect(['module' => "{$this->module}/{$this->controller}", 'field_group_id' => $field_group_id]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fields() {
|
||||||
|
$country_id = $this->request->get['country_id'] ?? false;
|
||||||
|
$fields = [];
|
||||||
|
|
||||||
|
if ($country_id) {
|
||||||
|
$field = new FieldSQL();
|
||||||
|
$options = $this->global;
|
||||||
|
$options['status'] = 1;
|
||||||
|
$options['country_id'] = $country_id;
|
||||||
|
unset($options['limit']);
|
||||||
|
$fields = $field->getAll($options)['field'] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($fields);
|
||||||
|
//return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$field_group_id = $this->request->get['field_group_id'] ?? false;
|
||||||
|
$this->view->field_group_id = $field_group_id;
|
||||||
|
|
||||||
|
parent::index();
|
||||||
|
|
||||||
|
//return;
|
||||||
|
$field_group_id = $this->request->get['field_group_id'] ?? false;
|
||||||
|
|
||||||
|
$fields = [];
|
||||||
|
|
||||||
|
if ($field_group_id) {
|
||||||
|
$field = new FieldSQL();
|
||||||
|
$fields = $field->getAll(['field_group_id' => [$field_group_id], 'limit' => 1000] + $this->global);
|
||||||
|
|
||||||
|
if ($fields['count'] > 0) {
|
||||||
|
foreach ($fields['field'] as &$field) {
|
||||||
|
$input['settings'] = json_decode($field['settings'], true);
|
||||||
|
$input['validation'] = json_decode($field['validation'], true);
|
||||||
|
$input['presentation'] = json_decode($field['presentation'], true);
|
||||||
|
$input['cols'] = $input['presentation']['cols'] ?? 'col';
|
||||||
|
$input['settings']['field_id'] = $field['field_id'];
|
||||||
|
$input['settings']['name'] = $input['settings']['name'] ?? '(none)';
|
||||||
|
$input['settings']['label'] = $input['settings']['label'] ?? '(none)';
|
||||||
|
$input['settings']['sort_order'] = $field['sort_order'];
|
||||||
|
$input['settings']['row'] = $field['row'];
|
||||||
|
$input['row'] = $input['settings']['row'] ?? 0;
|
||||||
|
|
||||||
|
$render = $this->renderField($field['type'], $field['field_id'], $input + $field);
|
||||||
|
$field['settings-tab'] = $render['settings'];
|
||||||
|
$field['validation-tab'] = $render['validation'];
|
||||||
|
$field['presentation-tab'] = $render['presentation'];
|
||||||
|
$field['field'] = $render['field'];
|
||||||
|
$field = $input + $field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->fieldTypes = getFieldTypes();
|
||||||
|
$this->view->postTypes = postTypes('post');
|
||||||
|
$this->view->productTypes = postTypes('product');
|
||||||
|
$this->view->fields = $fields['field'] ?? [];
|
||||||
|
|
||||||
|
$this->view->count = $fields['count'] ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
admin/controller/field/field-groups.php
Normal file
37
admin/controller/field/field-groups.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Field;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class FieldGroups extends Listing {
|
||||||
|
protected $type = 'field_group';
|
||||||
|
|
||||||
|
protected $controller = 'field-group';
|
||||||
|
|
||||||
|
protected $listController = 'field-group';
|
||||||
|
|
||||||
|
protected $list = 'field_group';
|
||||||
|
|
||||||
|
protected $module = 'field';
|
||||||
|
}
|
||||||
46
admin/controller/fields/field.php
Normal file
46
admin/controller/fields/field.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Fields;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
|
||||||
|
class Field extends Crud {
|
||||||
|
protected $type = 'field';
|
||||||
|
|
||||||
|
protected $controller = 'field';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
/*
|
||||||
|
$countryModel = new CountrySQL();
|
||||||
|
$options = $this->global;
|
||||||
|
unset($options['limit']);
|
||||||
|
$country = $countryModel->getAll($options);
|
||||||
|
*/
|
||||||
|
$this->view->countries = $country['country'] ?? [];
|
||||||
|
$this->view->status = [0 => __('Inactive'), 1 => __('Active')];
|
||||||
|
}
|
||||||
|
}
|
||||||
37
admin/controller/fields/field_group.php
Normal file
37
admin/controller/fields/field_group.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Fields;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class FieldGroup extends Listing {
|
||||||
|
protected $type = 'field_group';
|
||||||
|
|
||||||
|
protected $controller = 'field_group';
|
||||||
|
|
||||||
|
protected $listController = 'field_groups';
|
||||||
|
|
||||||
|
protected $list = 'field_group';
|
||||||
|
|
||||||
|
protected $module = 'fields';
|
||||||
|
}
|
||||||
89
admin/controller/index.php
Normal file
89
admin/controller/index.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller;
|
||||||
|
|
||||||
|
use Vvveb\Sql\StatSQL;
|
||||||
|
|
||||||
|
class Index extends Base {
|
||||||
|
function index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function stats() {
|
||||||
|
$options = [];
|
||||||
|
$stats = new StatSQL();
|
||||||
|
|
||||||
|
if (isset($this->request->get['end_date'])) {
|
||||||
|
$options['end_date'] = $this->request->get['end_date'];
|
||||||
|
} else {
|
||||||
|
$options['end_date'] = date('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request->get['start_date'])) {
|
||||||
|
$options['start_date'] = $this->request->get['start_date'];
|
||||||
|
} else {
|
||||||
|
$options['start_date'] = date('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
$users = filter_var(($this->request->get['users'] ?? 'false'), FILTER_VALIDATE_BOOLEAN);
|
||||||
|
$orders = filter_var(($this->request->get['sales'] ?? 'false'), FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
$results = $stats->getStats($options + $this->global);
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($results['orders'] as $order) {
|
||||||
|
$data[$order['date']]['orders'] = $order['orders'];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($results['users'] as $order) {
|
||||||
|
$data[$order['date']]['users'] = $order['users'];
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($data);
|
||||||
|
$labels = array_keys($data);
|
||||||
|
|
||||||
|
$usersData = [];
|
||||||
|
$ordersData = [];
|
||||||
|
|
||||||
|
foreach ($data as $date => $stat) {
|
||||||
|
$usersData[] = $stat['users'] ?? 0;
|
||||||
|
$ordersData[] = $stat['orders'] ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = ['labels' => $labels];
|
||||||
|
|
||||||
|
if ($users) {
|
||||||
|
$output['users'] = $usersData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($orders) {
|
||||||
|
$output['orders'] = $ordersData;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
function heartbeat() {
|
||||||
|
die('ok');
|
||||||
|
}
|
||||||
|
}
|
||||||
124
admin/controller/keycloak/callback.php
Normal file
124
admin/controller/keycloak/callback.php
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Keycloak SSO Callback Controller
|
||||||
|
*
|
||||||
|
* Handles: /admin/index.php?module=keycloak/callback
|
||||||
|
*
|
||||||
|
* This controller does NOT extend Base to avoid login requirement check
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Keycloak;
|
||||||
|
|
||||||
|
use Vvveb\System\Core\Request;
|
||||||
|
use Vvveb\System\Core\Response;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Session;
|
||||||
|
use Jumbojett\OpenIDConnectClient;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
|
||||||
|
#[\AllowDynamicProperties]
|
||||||
|
class Callback {
|
||||||
|
// Declare properties to avoid dynamic property warnings in PHP 8.2+
|
||||||
|
public $request;
|
||||||
|
public $response;
|
||||||
|
public $view;
|
||||||
|
public $session;
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
// Properties are injected by FrontController::di() automatically
|
||||||
|
// Suppress deprecation warnings from jumbojett library (PHP 8.5 compatibility)
|
||||||
|
// E_STRICT removed in PHP 8.4+, so we don't include it
|
||||||
|
// Suppress warnings temporarily to prevent output before headers
|
||||||
|
$oldErrorReporting = error_reporting(E_ALL & ~E_DEPRECATED & ~E_WARNING);
|
||||||
|
|
||||||
|
// Load Keycloak configuration from config file
|
||||||
|
$keycloakConfig = \Vvveb\config('keycloak', []);
|
||||||
|
|
||||||
|
// Fallback to hardcoded values if config file doesn't exist
|
||||||
|
$keycloakUrl = $keycloakConfig['server_url'] ?? 'https://connect.slm-lab.net/realms/cercle';
|
||||||
|
$keycloakClient = $keycloakConfig['client_id'] ?? 'page.slm-lab.net';
|
||||||
|
$keycloakSecret = $keycloakConfig['client_secret'] ?? 'IGFw1QWDs9xQ7OyRp6YM8VRgQxn09tFF';
|
||||||
|
|
||||||
|
// Redirect URL - MUST match exactly the one configured in Keycloak
|
||||||
|
$redirectUrl = $keycloakConfig['redirect_uri'] ?? 'https://www.slm-lab.net/admin/index.php?module=keycloak/callback';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create OpenID Connect client
|
||||||
|
$oidc = new OpenIDConnectClient(
|
||||||
|
$keycloakUrl,
|
||||||
|
$keycloakClient,
|
||||||
|
$keycloakSecret
|
||||||
|
);
|
||||||
|
|
||||||
|
$oidc->setRedirectURL($redirectUrl);
|
||||||
|
$oidc->addScope(['openid', 'profile', 'email']);
|
||||||
|
|
||||||
|
// Complete the OAuth2 flow (exchange code for tokens)
|
||||||
|
$oidc->authenticate();
|
||||||
|
|
||||||
|
// Get user information from Keycloak
|
||||||
|
$userInfo = $oidc->requestUserInfo();
|
||||||
|
|
||||||
|
// Restore error reporting
|
||||||
|
error_reporting($oldErrorReporting);
|
||||||
|
|
||||||
|
// Extract email from Keycloak response
|
||||||
|
$email = $userInfo->email ?? null;
|
||||||
|
|
||||||
|
if (!$email) {
|
||||||
|
throw new \Exception('Keycloak did not return an email address.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find admin user in Vvveb database using Vvveb API
|
||||||
|
// Only get active admins (status = 1)
|
||||||
|
$adminInfo = Admin::get([
|
||||||
|
'email' => $email,
|
||||||
|
'status' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$adminInfo) {
|
||||||
|
// User not found or not active - redirect to login with error
|
||||||
|
header('Location: /admin/index.php?module=user/login&error=' . urlencode("The email {$email} is not registered as an active admin in Vvveb."));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Vvveb admin session (same way Admin::login() does it)
|
||||||
|
$this->session->regenerateId(true);
|
||||||
|
|
||||||
|
// Remove password hash from session data
|
||||||
|
if (isset($adminInfo['password'])) {
|
||||||
|
unset($adminInfo['password']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set admin session (namespace 'admin' is used by Vvveb\System\User\Admin)
|
||||||
|
$this->session->set('admin', $adminInfo);
|
||||||
|
|
||||||
|
// Check if there's a redirect URL stored in session (from auto-login)
|
||||||
|
$redirectUrl = $this->session->get('keycloak_redirect');
|
||||||
|
if ($redirectUrl) {
|
||||||
|
// Remove redirect URL from session
|
||||||
|
$this->session->delete('keycloak_redirect');
|
||||||
|
// Redirect to original page
|
||||||
|
header('Location: ' . $redirectUrl);
|
||||||
|
} else {
|
||||||
|
// Redirect to admin dashboard
|
||||||
|
$adminPath = \Vvveb\adminPath() ?: '/admin/';
|
||||||
|
header('Location: ' . $adminPath . 'index.php');
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Restore error reporting
|
||||||
|
error_reporting($oldErrorReporting);
|
||||||
|
|
||||||
|
// Log error if logging is available
|
||||||
|
if (function_exists('error_log')) {
|
||||||
|
error_log('Keycloak SSO Error: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect to login page with error
|
||||||
|
header('Location: /admin/index.php?module=user/login&error=' . urlencode('Keycloak authentication failed: ' . $e->getMessage()));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
78
admin/controller/keycloak/login.php
Normal file
78
admin/controller/keycloak/login.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Keycloak SSO Login Controller
|
||||||
|
*
|
||||||
|
* Handles: /admin/index.php?module=keycloak/login
|
||||||
|
*
|
||||||
|
* This controller does NOT extend Base to avoid login requirement check
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Keycloak;
|
||||||
|
|
||||||
|
use Vvveb\System\Core\Request;
|
||||||
|
use Vvveb\System\Core\Response;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Session;
|
||||||
|
use Jumbojett\OpenIDConnectClient;
|
||||||
|
|
||||||
|
#[\AllowDynamicProperties]
|
||||||
|
class Login {
|
||||||
|
// Declare properties to avoid dynamic property warnings in PHP 8.2+
|
||||||
|
public $request;
|
||||||
|
public $response;
|
||||||
|
public $view;
|
||||||
|
public $session;
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
// Properties are injected by FrontController::di() automatically
|
||||||
|
// Suppress deprecation warnings from jumbojett library (PHP 8.5 compatibility)
|
||||||
|
// E_STRICT removed in PHP 8.4+, so we don't include it
|
||||||
|
// Suppress warnings temporarily to prevent output before headers
|
||||||
|
$oldErrorReporting = error_reporting(E_ALL & ~E_DEPRECATED & ~E_WARNING);
|
||||||
|
|
||||||
|
// Load Keycloak configuration from config file
|
||||||
|
$keycloakConfig = \Vvveb\config('keycloak', []);
|
||||||
|
|
||||||
|
// Fallback to hardcoded values if config file doesn't exist
|
||||||
|
$keycloakUrl = $keycloakConfig['server_url'] ?? 'https://connect.slm-lab.net/realms/cercle';
|
||||||
|
$keycloakClient = $keycloakConfig['client_id'] ?? 'page.slm-lab.net';
|
||||||
|
$keycloakSecret = $keycloakConfig['client_secret'] ?? 'IGFw1QWDs9xQ7OyRp6YM8VRgQxn09tFF';
|
||||||
|
|
||||||
|
// Redirect URL - MUST match exactly the one configured in Keycloak
|
||||||
|
$redirectUrl = $keycloakConfig['redirect_uri'] ?? 'https://www.slm-lab.net/admin/index.php?module=keycloak/callback';
|
||||||
|
|
||||||
|
// Get redirect parameter if present (for redirecting back to original page after login)
|
||||||
|
$originalRedirect = $this->request->get['redirect'] ?? null;
|
||||||
|
if ($originalRedirect) {
|
||||||
|
// Store original redirect URL in session for use after Keycloak callback
|
||||||
|
$this->session->set('keycloak_redirect', $originalRedirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create OpenID Connect client
|
||||||
|
$oidc = new OpenIDConnectClient(
|
||||||
|
$keycloakUrl,
|
||||||
|
$keycloakClient,
|
||||||
|
$keycloakSecret
|
||||||
|
);
|
||||||
|
|
||||||
|
$oidc->setRedirectURL($redirectUrl);
|
||||||
|
$oidc->addScope(['openid', 'profile', 'email']);
|
||||||
|
|
||||||
|
// Restore error reporting before redirect
|
||||||
|
error_reporting($oldErrorReporting);
|
||||||
|
|
||||||
|
// Redirect user to Keycloak for authentication
|
||||||
|
// This will send headers, so no output before this
|
||||||
|
$oidc->authenticate();
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Restore error reporting
|
||||||
|
error_reporting($oldErrorReporting);
|
||||||
|
|
||||||
|
// If redirect fails, redirect to login page with error
|
||||||
|
header('Location: /admin/index.php?module=user/login&error=' . urlencode('Keycloak authentication failed: ' . $e->getMessage()));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
admin/controller/listing.php
Normal file
62
admin/controller/listing.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\System\Traits\Listing as ListingTrait;
|
||||||
|
|
||||||
|
class Listing extends Base {
|
||||||
|
use ListingTrait {
|
||||||
|
ListingTrait::index as get;
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$results = $this->get();
|
||||||
|
|
||||||
|
$type = $this->type;
|
||||||
|
|
||||||
|
if (isset($results[$type])) {
|
||||||
|
$controller = $this->controller ?? $type;
|
||||||
|
$listController = $this->listController ?? $type;
|
||||||
|
$type_id = $this->type_id ?? "{$type}_id";
|
||||||
|
$data_id = $this->data_id ?? "{$type}_id";
|
||||||
|
$list = $this->list ?? $type;
|
||||||
|
$module = $this->module;
|
||||||
|
|
||||||
|
foreach ($results[$type] as $id => &$row) {
|
||||||
|
$params = ['module' => "$module/$controller", $type_id => $row[$type_id]];
|
||||||
|
$paramsList = ['module' => "$module/$listController", $type_id => $row[$type_id]];
|
||||||
|
$row['url'] = \Vvveb\url($params);
|
||||||
|
$row['edit-url'] = \Vvveb\url($params);
|
||||||
|
$row['delete-url'] = \Vvveb\url($paramsList + ['action' => 'delete', $type_id . '[]' => $row[$type_id]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->{$this->list} = $results[$this->type] ?? [];
|
||||||
|
|
||||||
|
$this->view->status = [0 => __('Disabled'), 1 => __('Enabled')];
|
||||||
|
$this->view->filter = $this->filter;
|
||||||
|
$this->view->count = $results['count'] ?? 0;
|
||||||
|
$this->view->limit = $results['limit'] ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
63
admin/controller/localization/countries.php
Normal file
63
admin/controller/localization/countries.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
use Vvveb\Sql\countrySQL;
|
||||||
|
|
||||||
|
class Countries extends Listing {
|
||||||
|
protected $type = 'country';
|
||||||
|
|
||||||
|
protected $controller = 'country';
|
||||||
|
|
||||||
|
protected $listController = 'countries';
|
||||||
|
|
||||||
|
protected $list = 'country';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
|
||||||
|
function countryAutocomplete() {
|
||||||
|
$country = new countrySQL();
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'start' => 0,
|
||||||
|
'limit' => 10,
|
||||||
|
'search' => trim($this->request->get['text']),
|
||||||
|
] + $this->global;
|
||||||
|
|
||||||
|
$results = $country->getAll($options);
|
||||||
|
|
||||||
|
$search = [];
|
||||||
|
|
||||||
|
foreach ($results['country'] as $country) {
|
||||||
|
//$country['image'] = Images::image($country['image'], 'country');
|
||||||
|
$search[$country['country_id']] = $country['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//echo json_encode($search);
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($search);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
admin/controller/localization/country.php
Normal file
33
admin/controller/localization/country.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
|
||||||
|
class Country extends Crud {
|
||||||
|
protected $type = 'country';
|
||||||
|
|
||||||
|
protected $controller = 'country';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
}
|
||||||
35
admin/controller/localization/currencies.php
Normal file
35
admin/controller/localization/currencies.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Currencies extends Listing {
|
||||||
|
protected $type = 'currency';
|
||||||
|
|
||||||
|
protected $list = 'currency';
|
||||||
|
|
||||||
|
protected $listController = 'currencies';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
}
|
||||||
31
admin/controller/localization/currency.php
Normal file
31
admin/controller/localization/currency.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
|
||||||
|
class Currency extends Crud {
|
||||||
|
protected $type = 'currency';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
}
|
||||||
121
admin/controller/localization/language.php
Normal file
121
admin/controller/localization/language.php
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use function Vvveb\download;
|
||||||
|
use function Vvveb\filter;
|
||||||
|
use function Vvveb\installedLanguages;
|
||||||
|
use function Vvveb\model;
|
||||||
|
use Vvveb\System\CacheManager;
|
||||||
|
|
||||||
|
class Language extends Crud {
|
||||||
|
protected $type = 'language';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
|
||||||
|
protected $installUrl = 'https://raw.githubusercontent.com/Vvveb/{code}/master/LC_MESSAGES/';
|
||||||
|
|
||||||
|
protected $files = ['vvveb.po'];
|
||||||
|
|
||||||
|
protected $listUrl = 'https://www.vvveb.com/page/contribute#language';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
//$this->redirect = false;
|
||||||
|
$this->model = model('language');
|
||||||
|
//check if a default language is set
|
||||||
|
$default = $this->model->get(['default' => 1]);
|
||||||
|
|
||||||
|
//if language set as default set other default language as false
|
||||||
|
if (isset($this->request->post['language']['default']) && $this->request->post['language']['default'] == '1') {
|
||||||
|
$this->model->edit(['language' => ['default' => 0]]);
|
||||||
|
} else {
|
||||||
|
//if no default language set then set this language as default
|
||||||
|
if (! $default) {
|
||||||
|
$this->request->post['language']['default'] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::save();
|
||||||
|
CacheManager::clearObjectCache(APP, 'languages');
|
||||||
|
$this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function install() {
|
||||||
|
$code = filter('/[-\w]+/', $this->request->post['code']);
|
||||||
|
$url = str_replace('{code}', $code, $this->installUrl);
|
||||||
|
$available = false;
|
||||||
|
|
||||||
|
require DIR_SYSTEM . 'functions' . DS . 'php-mo.php';
|
||||||
|
|
||||||
|
foreach ($this->files as $file) {
|
||||||
|
$translations = download($url . $file);
|
||||||
|
|
||||||
|
if ($translations) {
|
||||||
|
$available = true;
|
||||||
|
$folder = DIR_ROOT . 'locale' . DS . $code . DS . 'LC_MESSAGES';
|
||||||
|
$poFile = $folder . DS . $file;
|
||||||
|
@mkdir($folder, 0755 & ~umask(), true);
|
||||||
|
|
||||||
|
if (file_put_contents($poFile, $translations)) {
|
||||||
|
if (phpmo_convert($poFile)) {
|
||||||
|
$this->view->success['language'] = __('Language pack installed!');
|
||||||
|
} else {
|
||||||
|
$this->view->errors['language'] = __('Language compilation failed!');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error writing language files!');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $available) {
|
||||||
|
$this->view->errors[] = __('Language pack not available!');
|
||||||
|
$this->view->info[] = sprintf(__('Check available translations at %s'), '<a href="' . $this->listUrl . '" target="_blank">' . $this->listUrl . '</a>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
$languageList = include DIR_SYSTEM . 'data' . DS . 'languages-list.php';
|
||||||
|
$installed = installedLanguages();
|
||||||
|
|
||||||
|
foreach ($installed as $l) {
|
||||||
|
$languageList[$l]['installed'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->language_list = $languageList;
|
||||||
|
|
||||||
|
$this->view->status = [1 => __('Active'), 0 => __('Inactive')];
|
||||||
|
$this->view->default = $this->view->rtl = [0 => __('No'), 1 => __('Yes')];
|
||||||
|
}
|
||||||
|
}
|
||||||
33
admin/controller/localization/languages.php
Normal file
33
admin/controller/localization/languages.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Languages extends Listing {
|
||||||
|
protected $type = 'language';
|
||||||
|
|
||||||
|
protected $list = 'language';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
}
|
||||||
101
admin/controller/localization/region-group.php
Normal file
101
admin/controller/localization/region-group.php
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use Vvveb\Sql\CountrySQL;
|
||||||
|
use Vvveb\Sql\Region_GroupSQL;
|
||||||
|
use Vvveb\Sql\regionSQL;
|
||||||
|
|
||||||
|
class RegionGroup extends Crud {
|
||||||
|
protected $type = 'region_group';
|
||||||
|
|
||||||
|
protected $controller = 'region-group';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$region = $this->request->post['region'] ?? [];
|
||||||
|
$region_group_id = $this->request->get['region_group_id'] ?? false;
|
||||||
|
|
||||||
|
if ($region_group_id) {
|
||||||
|
$regionGroup = new Region_GroupSQL();
|
||||||
|
$result = $regionGroup->addRegions(['region_group_id' => $region_group_id, 'region_to_region_group' => $region]);
|
||||||
|
|
||||||
|
if ($result && isset($result['region_to_region_group'])) {
|
||||||
|
//$successMessage = __('Region saved!');
|
||||||
|
//$this->view->success[] = $successMessage;
|
||||||
|
$this->view->errors = [];
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function regions() {
|
||||||
|
$country_id = $this->request->get['country_id'] ?? false;
|
||||||
|
$regions = [];
|
||||||
|
|
||||||
|
if ($country_id) {
|
||||||
|
$region = new RegionSQL();
|
||||||
|
$options = $this->global;
|
||||||
|
$options['status'] = 1;
|
||||||
|
$options['country_id'] = $country_id;
|
||||||
|
unset($options['limit']);
|
||||||
|
$regions = $region->getAll($options)['region'] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($regions);
|
||||||
|
//return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
$region_group_id = $this->request->get['region_group_id'] ?? false;
|
||||||
|
|
||||||
|
$regions = [];
|
||||||
|
|
||||||
|
if ($region_group_id) {
|
||||||
|
$regionGroup = new Region_GroupSQL();
|
||||||
|
$regions = $regionGroup->getRegions(['region_group_id' => $region_group_id])['regions'] ?? [];
|
||||||
|
}
|
||||||
|
$this->view->regions = $regions;
|
||||||
|
$this->view->region_group_id = $region_group_id;
|
||||||
|
|
||||||
|
$countryModel = new CountrySQL();
|
||||||
|
$options = $this->global;
|
||||||
|
$options['status'] = 1;
|
||||||
|
unset($options['limit']);
|
||||||
|
$country = $countryModel->getAll($options);
|
||||||
|
|
||||||
|
$this->view->countries = $country['country'] ?? [];
|
||||||
|
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$controllerPath = $admin_path . 'index.php?module=localization/region-group';
|
||||||
|
$this->view->regionsUrl = "$controllerPath&action=regions";
|
||||||
|
}
|
||||||
|
}
|
||||||
37
admin/controller/localization/region-groups.php
Normal file
37
admin/controller/localization/region-groups.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class RegionGroups extends Listing {
|
||||||
|
protected $type = 'region_group';
|
||||||
|
|
||||||
|
protected $controller = 'region-group';
|
||||||
|
|
||||||
|
protected $listController = 'region-groups';
|
||||||
|
|
||||||
|
protected $list = 'region_group';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
}
|
||||||
47
admin/controller/localization/region.php
Normal file
47
admin/controller/localization/region.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use Vvveb\Sql\CountrySQL;
|
||||||
|
|
||||||
|
class Region extends Crud {
|
||||||
|
protected $type = 'region';
|
||||||
|
|
||||||
|
protected $controller = 'region';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
|
||||||
|
$countryModel = new CountrySQL();
|
||||||
|
$options = $this->global;
|
||||||
|
unset($options['limit']);
|
||||||
|
$country = $countryModel->getAll($options);
|
||||||
|
|
||||||
|
$this->view->countries = $country['country'] ?? [];
|
||||||
|
$this->view->status = [0 => __('Inactive'), 1 => __('Active')];
|
||||||
|
}
|
||||||
|
}
|
||||||
87
admin/controller/localization/regions.php
Normal file
87
admin/controller/localization/regions.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
use function Vvveb\humanReadable;
|
||||||
|
use function Vvveb\model;
|
||||||
|
|
||||||
|
class Regions extends Listing {
|
||||||
|
protected $type = 'region';
|
||||||
|
|
||||||
|
protected $controller = 'region';
|
||||||
|
|
||||||
|
protected $listController = 'regions';
|
||||||
|
|
||||||
|
protected $list = 'region';
|
||||||
|
|
||||||
|
protected $module = 'localization';
|
||||||
|
|
||||||
|
private function setStatus($status) {
|
||||||
|
$type = $this->type;
|
||||||
|
$type_id = $this->type_id ?? "{$type}_id";
|
||||||
|
|
||||||
|
if (APP == 'admin') {
|
||||||
|
$data_id = $this->request->post[$type_id];
|
||||||
|
} else {
|
||||||
|
$data_id = $this->request->post[$type_id] ?? $this->request->get[$type_id] ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data_id) {
|
||||||
|
if (is_numeric($data_id)) {
|
||||||
|
$data_id = [$data_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! isset($this->modelName)) {
|
||||||
|
$this->modelName = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
$model = model($this->modelName);
|
||||||
|
//$options = [$type_id => $data_id] + $this->global;
|
||||||
|
$result = $model->multiEdit([$type => ['status' => $status], $type_id => $data_id]);
|
||||||
|
$name = ucfirst(__($type));
|
||||||
|
|
||||||
|
if ($result && isset($result[$type])) {
|
||||||
|
if ($result[$type]) {
|
||||||
|
$this->view->success[] = sprintf(__('%s(s) status changed!'), humanReadable($name));
|
||||||
|
} else {
|
||||||
|
$this->view->info[] = sprintf(__('No rows affected!'), humanReadable($name));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error %s!'), humanReadable($name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($this->request->get[$type_id]);
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
function enable() {
|
||||||
|
$this->setStatus(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable() {
|
||||||
|
$this->setStatus(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
153
admin/controller/localization/translations.php
Normal file
153
admin/controller/localization/translations.php
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Localization;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\url;
|
||||||
|
|
||||||
|
require_once DIR_SYSTEM . 'functions' . DS . 'php-mo.php';
|
||||||
|
|
||||||
|
class Translations extends Base {
|
||||||
|
function domains() {
|
||||||
|
$lang = $this->request->get['lang'] ?? false;
|
||||||
|
|
||||||
|
if ($lang) {
|
||||||
|
$folder = DIR_ROOT . 'locale' . DS . $lang . DS . 'LC_MESSAGES' . DS;
|
||||||
|
$files = glob($folder . '*.po');
|
||||||
|
|
||||||
|
$url = ['module' => 'localization/translations', 'action' => 'domain', 'lang' => $lang];
|
||||||
|
//add user if does not exist yet
|
||||||
|
$domains['user'] = url($url + ['domain' => 'user']);
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$domain = str_replace('.po', '', basename($file));
|
||||||
|
$domains[$domain] = url($url + ['domain' => $domain]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->domains = $domains;
|
||||||
|
$this->view->count = count($domains);
|
||||||
|
} else {
|
||||||
|
$this->notFound(__('Invalid request!'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function compile() {
|
||||||
|
//add default translations first to be overriden by all others
|
||||||
|
$domains = ['vvveb'];
|
||||||
|
$message = '';
|
||||||
|
$view = $this->view;
|
||||||
|
|
||||||
|
$folder = DIR_ROOT . 'locale' . DS . $view->lang . DS . 'LC_MESSAGES' . DS;
|
||||||
|
|
||||||
|
foreach (glob("$folder/*.po") as $file) {
|
||||||
|
$domain = str_replace('.po', '', basename($file));
|
||||||
|
|
||||||
|
if ($domain !== 'user' && $domain !== 'vvveb') {
|
||||||
|
$domains[] = $domain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add user translations last to override all others
|
||||||
|
$domains[] = 'user';
|
||||||
|
|
||||||
|
foreach ($domains as $domain) {
|
||||||
|
$poFile = $folder . $domain . '.po';
|
||||||
|
|
||||||
|
if (file_exists($poFile) && ($translations = phpmo_parse_po_file($poFile) ?: []) && is_array($translations)) {
|
||||||
|
$view->translations = array_merge($view->translations, $translations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//compile
|
||||||
|
if (phpmo_write_mo_file($view->translations, $folder . 'vvveb-new.mo')) {
|
||||||
|
if (rename($folder . 'vvveb-new.mo', $folder . 'vvveb.mo')) {
|
||||||
|
clearstatcache();
|
||||||
|
$message .= "\n" . __('Compiled!');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message .= "\n" . __('Error compiling!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$view = $this->view;
|
||||||
|
$translations = $this->request->post['translations'] ?? [];
|
||||||
|
$this->response->setType('json');
|
||||||
|
|
||||||
|
$message = __('No data!');
|
||||||
|
|
||||||
|
if ($translations) {
|
||||||
|
//use common check po file and parse
|
||||||
|
$this->domain();
|
||||||
|
|
||||||
|
$folder = DIR_ROOT . 'locale' . DS . $view->lang . DS . 'LC_MESSAGES' . DS;
|
||||||
|
|
||||||
|
foreach ($translations as $text => $translation) {
|
||||||
|
$view->translations[$text] = ['msgid' => $text, 'msgstr' => [$translation]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phpmo_write_po_file($view->translations, $folder . $view->domain . '.po')) {
|
||||||
|
$message = __('Saved!');
|
||||||
|
$message .= $this->compile();
|
||||||
|
} else {
|
||||||
|
$message = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = ['message' => $message];
|
||||||
|
$this->response->output($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function domain() {
|
||||||
|
$view = $this->view;
|
||||||
|
$view->lang = $lang = $this->request->get['lang'] ?? false;
|
||||||
|
$view->domain = $domain = $this->request->get['domain'] ?? false;
|
||||||
|
$url = ['module' => 'localization/translations', 'lang' => $lang, 'domain' => $domain];
|
||||||
|
$view->domainsUrl = url($url + ['action' => 'domains']);
|
||||||
|
$view->saveUrl = url($url + ['action' => 'save']);
|
||||||
|
|
||||||
|
if ($lang && $domain) {
|
||||||
|
$poFile = DIR_ROOT . 'locale' . DS . $lang . DS . 'LC_MESSAGES' . DS . $domain . '.po';
|
||||||
|
$view->poFile = $poFile;
|
||||||
|
|
||||||
|
if (file_exists($poFile)) {
|
||||||
|
$view->translations = phpmo_parse_po_file($poFile);
|
||||||
|
|
||||||
|
if (! is_writeable($poFile)) {
|
||||||
|
$view->info = [__('Po file not writable, saving will not work!')];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($domain == 'user') {
|
||||||
|
//if domain is user then create it
|
||||||
|
$view->translations = [];
|
||||||
|
} else {
|
||||||
|
$this->notFound(__('Po file does not exist!'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->notFound(__('Invalid request!'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
admin/controller/media/media.php
Normal file
80
admin/controller/media/media.php
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Media;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\sanitizeFileName;
|
||||||
|
use Vvveb\Sql\media_ContentSQL;
|
||||||
|
use Vvveb\System\Traits\Media as MediaTrait;
|
||||||
|
|
||||||
|
class Media extends Base {
|
||||||
|
use MediaTrait;
|
||||||
|
|
||||||
|
protected $dirMedia = DIR_MEDIA;
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$adminPath = \Vvveb\adminPath();
|
||||||
|
$controllerPath = $adminPath . 'index.php?module=media/media';
|
||||||
|
$this->setMediaEndpoints($controllerPath);
|
||||||
|
|
||||||
|
$this->view->mediaContentUrl = "$controllerPath&action=mediaContent";
|
||||||
|
}
|
||||||
|
|
||||||
|
function mediaContentSave() {
|
||||||
|
$file = sanitizeFileName($this->request->post['file']);
|
||||||
|
$content = ($this->request->post['media_content'] ?? []);
|
||||||
|
$result = false;
|
||||||
|
|
||||||
|
if ($file && $content) {
|
||||||
|
$mediaContent = new media_ContentSQL();
|
||||||
|
$media = $mediaContent->get(['file' => $file] + $this->global);
|
||||||
|
|
||||||
|
if ($media) {
|
||||||
|
$result = $mediaContent->edit(['media_id' => $media['media_id'], 'media_content' => $content, 'media' => []]);
|
||||||
|
} else {
|
||||||
|
$result = $mediaContent->add(['media' => ['file' => $file], 'media_content' => $content]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$message = ['success' => true, 'message' => __('Saved!')];
|
||||||
|
} else {
|
||||||
|
$message = ['success' => false, 'message' => __('Error saving!')];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mediaContent() {
|
||||||
|
$file = sanitizeFileName($this->request->get['file']);
|
||||||
|
$themeFolder = DIR_MEDIA;
|
||||||
|
|
||||||
|
$mediaContent = new media_ContentSQL();
|
||||||
|
$result = $mediaContent->getContent(['file' => $file] + $this->global);
|
||||||
|
|
||||||
|
$this->response->setType('json');
|
||||||
|
$this->response->output($result ?? []);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
admin/controller/order/coupon.php
Normal file
71
admin/controller/order/coupon.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use Vvveb\Sql\CouponSQL;
|
||||||
|
|
||||||
|
class Coupon extends Crud {
|
||||||
|
protected $type = 'coupon';
|
||||||
|
|
||||||
|
protected $controller = 'coupon';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
parent::save();
|
||||||
|
|
||||||
|
$post = &$this->request->post;
|
||||||
|
$get = &$this->request->get;
|
||||||
|
$coupon_id = $post['coupon_id'] ?? $get['coupon_id'] ?? false;
|
||||||
|
$products = $post['coupon_product'] ?? [];
|
||||||
|
$taxonomy = $post['coupon_taxonomy'] ?? [];
|
||||||
|
|
||||||
|
$couponSQL = new CouponSQL();
|
||||||
|
|
||||||
|
if ($products) {
|
||||||
|
$couponSQL->setProducts(['coupon_product' => $products, 'coupon_id' => $coupon_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($taxonomy) {
|
||||||
|
$couponSQL->setTaxonomies(['coupon_taxonomy' => $taxonomy, 'coupon_id' => $coupon_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
$get = &$this->request->get;
|
||||||
|
$coupon_id = $get['coupon_id'] ?? false;
|
||||||
|
|
||||||
|
$couponSQL = new CouponSQL();
|
||||||
|
|
||||||
|
$this->view->coupon += $couponSQL->getProducts(['coupon_id' => $coupon_id] + $this->global) ?? [];
|
||||||
|
$this->view->coupon += $couponSQL->getTaxonomies(['coupon_id' => $coupon_id] + $this->global) ?? [];
|
||||||
|
|
||||||
|
$this->view->type = ['P' => __('Percentage'), 'F' => __('Fixed')];
|
||||||
|
$this->view->free_shipping = $this->view->logged_in = ['0' => __('No'), '1' => __('Yes')];
|
||||||
|
}
|
||||||
|
}
|
||||||
37
admin/controller/order/coupons.php
Normal file
37
admin/controller/order/coupons.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Coupons extends Listing {
|
||||||
|
protected $type = 'coupon';
|
||||||
|
|
||||||
|
protected $controller = 'coupon';
|
||||||
|
|
||||||
|
protected $listController = 'coupons';
|
||||||
|
|
||||||
|
protected $list = 'coupon';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
}
|
||||||
317
admin/controller/order/order.php
Normal file
317
admin/controller/order/order.php
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use Vvveb\Controller\Content\AutocompleteTrait;
|
||||||
|
use function Vvveb\email;
|
||||||
|
use function Vvveb\orderStatusBadgeClass;
|
||||||
|
use function Vvveb\paymentStatusBadgeClass;
|
||||||
|
use function Vvveb\prefixArrayKeys;
|
||||||
|
use function Vvveb\shippingStatusBadgeClass;
|
||||||
|
use function Vvveb\siteSettings;
|
||||||
|
use Vvveb\Sql\Order_LogSQL;
|
||||||
|
use Vvveb\Sql\OrderSQL;
|
||||||
|
use Vvveb\System\Cart\Cart;
|
||||||
|
use Vvveb\System\Cart\Currency;
|
||||||
|
use Vvveb\System\Cart\Order as SystemOrder;
|
||||||
|
use Vvveb\System\Cart\OrderCart;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
use Vvveb\System\Payment;
|
||||||
|
use Vvveb\System\Shipping;
|
||||||
|
use Vvveb\System\Sites;
|
||||||
|
use Vvveb\System\Validator;
|
||||||
|
use function Vvveb\url;
|
||||||
|
|
||||||
|
class Order extends Base {
|
||||||
|
use AutocompleteTrait;
|
||||||
|
|
||||||
|
protected $type = 'order';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
//$_GET['order_id'] = 1;
|
||||||
|
$site = siteSettings($this->global['site_id']);
|
||||||
|
$options = array_intersect_key($site,
|
||||||
|
array_flip(['weight_type_id', 'length_type_id', 'currency_id', 'country_id']));
|
||||||
|
|
||||||
|
$cart = Cart::getInstance($options);
|
||||||
|
$payment = Payment::getInstance();
|
||||||
|
$shipping = Shipping::getInstance();
|
||||||
|
$view = $this->view;
|
||||||
|
$order = [];
|
||||||
|
|
||||||
|
/*
|
||||||
|
$order_id = 1;
|
||||||
|
//get site default country and region for taxes
|
||||||
|
$site = siteSettings($this->global['site_id']);
|
||||||
|
$options = $this->global + $site;
|
||||||
|
var_dump($options);
|
||||||
|
unset($options['admin_id']);
|
||||||
|
$order = new OrderCart($order_id, $options);
|
||||||
|
$order->add(1);
|
||||||
|
//$order->add(2);
|
||||||
|
$order->updateCart();
|
||||||
|
var_dump($order->getTotals());
|
||||||
|
//var_dump($order->getGrandTotal());
|
||||||
|
var_dump($order->getGrandTotalFormatted());
|
||||||
|
//var_dump($order->getAll());
|
||||||
|
die(0);
|
||||||
|
*/
|
||||||
|
//$order->addProduct(['order_id' => $order_id, 'product' => $product, 'product_options' => []]);
|
||||||
|
|
||||||
|
if (isset($this->request->get['order_id'])) {
|
||||||
|
$options = ['order_id' => (int)$this->request->get['order_id'], 'type' => $this->type] + $this->global;
|
||||||
|
|
||||||
|
$orders = new OrderSQL();
|
||||||
|
$results = $orders->get($options);
|
||||||
|
|
||||||
|
if ($results['order']) {
|
||||||
|
$currency = Currency::getInstance();
|
||||||
|
|
||||||
|
if (isset($results['products'])) {
|
||||||
|
foreach ($results['products'] as $id => &$product) {
|
||||||
|
$product['url'] = htmlspecialchars(\Vvveb\url('product/product/index', $product));
|
||||||
|
|
||||||
|
if (isset($product['images'])) {
|
||||||
|
$product['images'] = json_decode($product['images'], true);
|
||||||
|
|
||||||
|
foreach ($product['images'] as &$image) {
|
||||||
|
$image['image'] = Images::image($image['image'], 'product');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($product['option_value'])) {
|
||||||
|
$product['option_value'] = json_decode($product['option_value'], true);
|
||||||
|
|
||||||
|
foreach ($product['option_value'] as &$option) {
|
||||||
|
if (isset($option['price'])) {
|
||||||
|
$option['price_formatted'] = $currency->format($option['price']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($product['image']) && $product['image']) {
|
||||||
|
$product['image'] =Images::image($product['image'], 'product');
|
||||||
|
//$product['images'][] = ['image' => Images::image($product['image'], 'product')];
|
||||||
|
}
|
||||||
|
|
||||||
|
$product['price_formatted'] = $currency->format($product['price']);
|
||||||
|
$product['tax_formatted'] = $currency->format($product['tax']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($results['total'] as $id => &$total) {
|
||||||
|
$total['value_formatted'] = $currency->format($total['value']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = &$results['order'];
|
||||||
|
$order['user_url'] = \Vvveb\url(['module' => 'user/user', 'user_id' => $order['user_id']]);
|
||||||
|
$order['total_formatted'] = $currency->format($order['total']);
|
||||||
|
$order['shipping_data'] = json_decode($order['shipping_data'] ?? '', true);
|
||||||
|
$order['payment_data'] = json_decode($order['payment_data'] ?? '', true);
|
||||||
|
$order['class'] = orderStatusBadgeClass($order['order_status_id']);
|
||||||
|
$order['payment_class'] = paymentStatusBadgeClass($order['payment_status_id']);
|
||||||
|
$order['shipping_class'] = shippingStatusBadgeClass($order['shipping_status_id']);
|
||||||
|
|
||||||
|
$order += prefixArrayKeys('shipping_', $order['shipping_data']) ?? [];
|
||||||
|
$order += prefixArrayKeys('payment_', $order['payment_data']) ?? [];
|
||||||
|
|
||||||
|
$data = $orders->getData($order);
|
||||||
|
|
||||||
|
$view->set($data);
|
||||||
|
$view->set($results);
|
||||||
|
|
||||||
|
$url = ['module' => 'order/order', 'action' => 'print', 'order_id' => $order['order_id']];
|
||||||
|
$view->printUrl = \Vvveb\url($url);
|
||||||
|
$view->printShippingUrl = \Vvveb\url(['action' => 'printShipping'] + $url);
|
||||||
|
$view->printInvoiceUrl = \Vvveb\url(['action' => 'printInvoice'] + $url);
|
||||||
|
} else {
|
||||||
|
$this->notFound(__('Order not found!'));
|
||||||
|
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//new order
|
||||||
|
$orders = new OrderSQL();
|
||||||
|
$data = $orders->getData($this->global);
|
||||||
|
$view->set($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->order_payment = $payment->getMethods($order);
|
||||||
|
$this->view->order_shipping = $shipping->getMethods($order);
|
||||||
|
}
|
||||||
|
|
||||||
|
function print() {
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function printShipping() {
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function printInvoice() {
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function cart() {
|
||||||
|
$order_id = $this->request->get['order_id'] ?? false;
|
||||||
|
$product_id = $this->request->post['product_id'] ?? false;
|
||||||
|
$quantity = $this->request->post['quantity'] ?? 1;
|
||||||
|
$name = $this->request->post['name'] ?? '';
|
||||||
|
$model = $this->request->post['model'] ?? '';
|
||||||
|
$price = $this->request->post['price'] ?? 1;
|
||||||
|
|
||||||
|
if ($order_id && $product_id) {
|
||||||
|
$product = compact('product_id','quantity', 'name', 'price', 'model');
|
||||||
|
|
||||||
|
$site = siteSettings($this->global['site_id']);
|
||||||
|
$options = $this->global + $site;
|
||||||
|
unset($options['admin_id']);
|
||||||
|
|
||||||
|
$order = new OrderCart($order_id, $options);
|
||||||
|
$order->addOrderProduct($product_id, false, $quantity, []);
|
||||||
|
$order->updateCart();
|
||||||
|
$order->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendNotification($order_id, $customer_order_id, $email, $message) {
|
||||||
|
try {
|
||||||
|
$error = __('Error sending order confirmation mail!');
|
||||||
|
$title = sprintf(__('Order update #%s'), $customer_order_id);
|
||||||
|
|
||||||
|
$options = ['order_id' => $order_id] + $this->global;
|
||||||
|
|
||||||
|
$orders = new OrderSQL();
|
||||||
|
$results = $orders->get($options);
|
||||||
|
|
||||||
|
if (! email([$email], $title, 'order/update', ['message' => $message, 'title' => $title] + $results + $this->global, [], 'app')) {
|
||||||
|
$this->session->set('errors', $error);
|
||||||
|
$this->view->errors[] = $error;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
if (DEBUG) {
|
||||||
|
$error .= "\n" . $e->getMessage();
|
||||||
|
}
|
||||||
|
$this->session->set('errors', $error);
|
||||||
|
$this->view->errors[] = $error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveLog() {
|
||||||
|
$order_id = $this->request->get['order_id'] ?? false;
|
||||||
|
$customer_order_id = $this->request->post['customer_order_id'] ?? false;
|
||||||
|
$log = $this->request->post['log'] ?? [];
|
||||||
|
$notify = $log['notify'] ?? false;
|
||||||
|
$public = $log['public'] ?? false;
|
||||||
|
$view = $this->view;
|
||||||
|
|
||||||
|
$this->index();
|
||||||
|
|
||||||
|
if ($order_id && $log) {
|
||||||
|
// update order status with the last log status
|
||||||
|
$order = new OrderSQL();
|
||||||
|
$result = $order->edit(['order_id' => $order_id, 'order' => ['order_status_id' => $log['order_status_id']]]);
|
||||||
|
|
||||||
|
if (isset($result['order'])/* && $result['order']*/) {
|
||||||
|
$orderLog = new Order_LogSQL();
|
||||||
|
$result = $orderLog->add(['order_id' => $order_id, 'order_log' => $log]);
|
||||||
|
|
||||||
|
if (isset($result['order_log']) && $result['order_log']) {
|
||||||
|
$view->success = [__('Order status saved!')];
|
||||||
|
|
||||||
|
$this->view->log[] = $log;
|
||||||
|
|
||||||
|
if ($notify) {
|
||||||
|
$message = '';
|
||||||
|
|
||||||
|
if ($public) {
|
||||||
|
$message = $log['note'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$email = $this->view->order['email'];
|
||||||
|
$this->sendNotification($order_id, $customer_order_id, $email, $message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$view->errors[] = $orderLog->error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$view->errors[] = $order->error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$validator = new Validator(['checkout', 'order', 'checkout_shipping', 'checkout_billing']);
|
||||||
|
$view = view :: getInstance();
|
||||||
|
$order_id = $this->request->get['order_id'] ?? false;
|
||||||
|
$order = $this->request->post ?? [];
|
||||||
|
|
||||||
|
$site = Sites :: getSiteData();
|
||||||
|
|
||||||
|
$order_url = url('user/orders', [
|
||||||
|
'host' => $site['host'] ?? false,
|
||||||
|
'scheme' => $_SERVER['REQUEST_SCHEME'] ?? 'http',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$order['site_url'] = $site['host'];
|
||||||
|
$order['site_name'] = $site['name'];
|
||||||
|
$order['products'] = [];
|
||||||
|
$order['totals'] = [];
|
||||||
|
|
||||||
|
if (($errors = $validator->validate($order)) === true) {
|
||||||
|
$orders = new OrderSQL();
|
||||||
|
|
||||||
|
if ($order_id) {
|
||||||
|
$result = $orders->edit(['order_id' => $order_id, 'order' => $order]);
|
||||||
|
|
||||||
|
if ($result >= 0) {
|
||||||
|
$view->success = [__('Order saved')];
|
||||||
|
} else {
|
||||||
|
$view->errors = [$orders->error];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$systemOrder = SystemOrder::getInstance();
|
||||||
|
$order = $systemOrder->add($order + $this->global);
|
||||||
|
$order_id = $order['order_id'];
|
||||||
|
|
||||||
|
if (isset($order_id)) {
|
||||||
|
$message = __('Order saved!');
|
||||||
|
$this->view->success['get'] = $message;
|
||||||
|
$url = ['module' => 'order/order', 'order_id' => $order_id, 'success' => $message];
|
||||||
|
$this->redirect($url);
|
||||||
|
} else {
|
||||||
|
$view->errors = [$orders->error];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$view->errors = $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index();
|
||||||
|
}
|
||||||
|
}
|
||||||
89
admin/controller/order/orders.php
Normal file
89
admin/controller/order/orders.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\orderStatusBadgeClass;
|
||||||
|
use function Vvveb\paymentStatusBadgeClass;
|
||||||
|
use function Vvveb\shippingStatusBadgeClass;
|
||||||
|
use Vvveb\Sql\OrderSQL;
|
||||||
|
use Vvveb\System\Cart\Currency;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
|
||||||
|
class Orders extends Base {
|
||||||
|
//check for order save permission
|
||||||
|
protected $additionalPermissionCheck = ['order/order/save'];
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
$order_id = $this->request->post['order_id'] ?? $this->request->get['order_id'] ?? false;
|
||||||
|
|
||||||
|
if ($order_id) {
|
||||||
|
if (is_numeric($order_id)) {
|
||||||
|
$order_id = [$order_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$orders = new OrderSQL();
|
||||||
|
$options = ['order_id' => $order_id] + $this->global;
|
||||||
|
$result = $orders->delete($options);
|
||||||
|
|
||||||
|
if ($result && isset($result['order'])) {
|
||||||
|
$this->view->success[] = __('Order(s) deleted!');
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error deleting order!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = View :: getInstance();
|
||||||
|
$orders = new OrderSQL();
|
||||||
|
$currency = Currency::getInstance();
|
||||||
|
$this->filter = $this->request->get['filter'] ?? [];
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
] + $this->global + $this->filter;
|
||||||
|
unset($options['user_id']);
|
||||||
|
|
||||||
|
$results = $orders->getAll($options);
|
||||||
|
|
||||||
|
if ($results['order']) {
|
||||||
|
foreach ($results['order'] as $id => &$order) {
|
||||||
|
$order['total_formatted'] = $currency->format($order['total']);
|
||||||
|
$order['class'] = orderStatusBadgeClass($order['order_status_id']);
|
||||||
|
$order['payment_class'] = paymentStatusBadgeClass($order['payment_status_id']);
|
||||||
|
$order['shipping_class'] = shippingStatusBadgeClass($order['shipping_status_id']);
|
||||||
|
$order['delete-url'] = \Vvveb\url(['module' => 'order/orders', 'action' => 'delete'] + ['order_id[]' => $order['order_id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $orders->getData($this->global);
|
||||||
|
$view->set($data);
|
||||||
|
|
||||||
|
$view->filter = $this->filter;
|
||||||
|
$view->orders = $results['order'];
|
||||||
|
$view->count = $results['count'];
|
||||||
|
}
|
||||||
|
}
|
||||||
53
admin/controller/order/return-order.php
Normal file
53
admin/controller/order/return-order.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use Vvveb\Sql\Return_ReasonSQL;
|
||||||
|
use Vvveb\Sql\Return_ResolutionSQL;
|
||||||
|
use Vvveb\Sql\Return_StatusSQL;
|
||||||
|
|
||||||
|
//Return is a reserved keyword using ReturnOrder and return-order instead
|
||||||
|
class ReturnOrder extends Crud {
|
||||||
|
protected $type = 'return';
|
||||||
|
|
||||||
|
protected $controller = 'return-order';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent :: index();
|
||||||
|
|
||||||
|
$resolution = new Return_ResolutionSQL();
|
||||||
|
$reason = new Return_ReasonSQL();
|
||||||
|
$status = new Return_StatusSQL();
|
||||||
|
|
||||||
|
$resolutions = $resolution->getAll($this->global)['return_resolution'] ?? [];
|
||||||
|
$reasons = $reason->getAll($this->global)['return_reason'] ?? [];
|
||||||
|
$statuses = $status->getAll($this->global)['return_status'] ?? [];
|
||||||
|
|
||||||
|
$this->view->return_resolution_id = $resolutions;
|
||||||
|
$this->view->return_reason_id = $reasons;
|
||||||
|
$this->view->return_status_id = $statuses;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
admin/controller/order/returns.php
Normal file
39
admin/controller/order/returns.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Returns extends Listing {
|
||||||
|
protected $additionalPermissionCheck = ['order/return-order/save'];
|
||||||
|
|
||||||
|
protected $type = 'return';
|
||||||
|
|
||||||
|
protected $controller = 'return-order';
|
||||||
|
|
||||||
|
protected $listController = 'returns';
|
||||||
|
|
||||||
|
protected $list = 'return';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
}
|
||||||
42
admin/controller/order/subscription.php
Normal file
42
admin/controller/order/subscription.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
|
||||||
|
class Subscription extends Crud {
|
||||||
|
protected $type = 'subscription';
|
||||||
|
|
||||||
|
protected $controller = 'subscription';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent :: index();
|
||||||
|
|
||||||
|
$this->view->period = ['day' => __('Day'), 'week' => __('Week'), 'month' => __('Month'), 'year' => __('Year')];
|
||||||
|
$this->view->trial_period = $this->view->period;
|
||||||
|
$this->view->trial_status = $this->view->status;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
admin/controller/order/subscriptions.php
Normal file
39
admin/controller/order/subscriptions.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Subscriptions extends Listing {
|
||||||
|
protected $additionalPermissionCheck = ['order/subscription/save'];
|
||||||
|
|
||||||
|
protected $type = 'subscription';
|
||||||
|
|
||||||
|
protected $controller = 'subscription';
|
||||||
|
|
||||||
|
protected $listController = 'subscriptions';
|
||||||
|
|
||||||
|
protected $list = 'subscription';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
}
|
||||||
33
admin/controller/order/voucher.php
Normal file
33
admin/controller/order/voucher.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
|
||||||
|
class Voucher extends Crud {
|
||||||
|
protected $type = 'voucher';
|
||||||
|
|
||||||
|
protected $controller = 'voucher';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
}
|
||||||
37
admin/controller/order/vouchers.php
Normal file
37
admin/controller/order/vouchers.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Order;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Vouchers extends Listing {
|
||||||
|
protected $type = 'voucher';
|
||||||
|
|
||||||
|
protected $controller = 'voucher';
|
||||||
|
|
||||||
|
protected $listController = 'vouchers';
|
||||||
|
|
||||||
|
protected $list = 'voucher';
|
||||||
|
|
||||||
|
protected $module = 'order';
|
||||||
|
}
|
||||||
127
admin/controller/plugin/market.php
Normal file
127
admin/controller/plugin/market.php
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Plugin;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use Vvveb\System\CacheManager;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Extensions\Plugins;
|
||||||
|
use Vvveb\System\Validator;
|
||||||
|
|
||||||
|
class Market extends Base {
|
||||||
|
function install() {
|
||||||
|
$slug = $this->request->post['slug'] ?? false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($slug) {
|
||||||
|
$plugin = Plugins :: getMarketList(['slug' => $slug])['plugins'];
|
||||||
|
|
||||||
|
if ($plugin && isset($plugin[0])) {
|
||||||
|
$pluginInfo = $plugin[0];
|
||||||
|
extract($pluginInfo);
|
||||||
|
$url = Plugins :: marketUrl();
|
||||||
|
$downloadLink = "$url$download_link";
|
||||||
|
|
||||||
|
$this->view->log[] = sprintf(__('Installing "%s"'), $name);
|
||||||
|
$this->view->log[] = sprintf(__('Downloading "%s"'), $downloadLink);
|
||||||
|
|
||||||
|
if ($tempFile = Plugins :: download($downloadLink)) {
|
||||||
|
$this->view->log[] = sprintf(__('Unpacking "%s"'), $tempFile);
|
||||||
|
|
||||||
|
if (Plugins :: install($tempFile, $slug)) {
|
||||||
|
CacheManager::clearObjectCache('vvveb', 'plugins_list_' . $this->global['site_id']);
|
||||||
|
$pluginName = \Vvveb\humanReadable($slug);
|
||||||
|
$pluginName = "<b>$pluginName</b>";
|
||||||
|
$pluginActivateUrl = \Vvveb\url(['module' => 'plugin/plugins', 'action'=> 'activate', 'plugin' => $slug]);
|
||||||
|
|
||||||
|
$successMessage = sprintf(__('Plugin %s was successfully installed!'), $pluginName, $pluginActivateUrl);
|
||||||
|
$this->view->log[] = $successMessage;
|
||||||
|
|
||||||
|
$successMessage .= "<button class='btn btn-primary btn-sm m-2' formaction='$pluginActivateUrl' name='plugin' value='$slug'>" . __('Activate plugin') . '</button>';
|
||||||
|
$this->view->success[] = $successMessage;
|
||||||
|
} else {
|
||||||
|
$error = sprintf(__('Error installing "%s"!'), $slug);
|
||||||
|
$this->view->log[] = $error;
|
||||||
|
$this->view->errors[] = $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink($tempFile);
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error downloading "%s" from %s!'), $slug, $downloadLink);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Plugin "%s" not found!'), $slug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$error = $e->getMessage();
|
||||||
|
$this->view->errors[] = $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request->get['json'])) {
|
||||||
|
$this->view->setType('json');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function download() {
|
||||||
|
$slug = $this->request->get['slug'];
|
||||||
|
|
||||||
|
if ($slug) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = View :: getInstance();
|
||||||
|
|
||||||
|
$validator = new Validator(['plugins']);
|
||||||
|
|
||||||
|
//allow only fields that are in the validator list and remove the rest
|
||||||
|
$request = array_filter($validator->filter($this->request->get));
|
||||||
|
$plugins = [];
|
||||||
|
|
||||||
|
$request['limit'] = $this->view->limit = 8;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$plugins = Plugins :: getMarketList($request);
|
||||||
|
$categories = Plugins :: getMarketCategories(['limit' => 100] + $request, 'categories');
|
||||||
|
$installed = Plugins :: getList($this->global['site_id']);
|
||||||
|
|
||||||
|
foreach ($plugins['plugins'] as &$plugin) {
|
||||||
|
$plugin['installed'] = isset($installed[$plugin['slug']]);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$view->warning[] = __('Failed to connect to marketplace');
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
$view->errors[] = $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin_path = \Vvveb\adminPath();
|
||||||
|
$view->installUrl = $admin_path . 'index.php?module=plugin/market&action=install&json';
|
||||||
|
$view->categories = $categories['categories'];
|
||||||
|
$view->set($request);
|
||||||
|
$view->set($plugins);
|
||||||
|
}
|
||||||
|
}
|
||||||
275
admin/controller/plugin/plugins.php
Normal file
275
admin/controller/plugin/plugins.php
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Plugin;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Base;
|
||||||
|
use function Vvveb\fileUploadErrMessage;
|
||||||
|
use function Vvveb\rrmdir;
|
||||||
|
use Vvveb\System\CacheManager;
|
||||||
|
use function Vvveb\System\Core\exceptionToArray;
|
||||||
|
use Vvveb\System\Core\FrontController;
|
||||||
|
use Vvveb\System\Core\View;
|
||||||
|
use Vvveb\System\Extensions\Plugins as PluginsList;
|
||||||
|
use Vvveb\System\User\Admin;
|
||||||
|
|
||||||
|
class Plugins extends Base {
|
||||||
|
function init() {
|
||||||
|
parent::init();
|
||||||
|
|
||||||
|
$this->plugin = $this->request->post['plugin'] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
$slug = $this->request->post['plugin'] ?? false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($slug) {
|
||||||
|
$plugin = PluginsList :: getMarketList(['slug' => $slug])['plugins'];
|
||||||
|
|
||||||
|
if ($plugin && isset($plugin[0])) {
|
||||||
|
$pluginInfo = $plugin[0];
|
||||||
|
extract($pluginInfo);
|
||||||
|
$url = PluginsList :: marketUrl();
|
||||||
|
$downloadLink = "$url$download_link";
|
||||||
|
|
||||||
|
$this->view->log[] = sprintf(__('Installing "%s"'), $name);
|
||||||
|
$this->view->log[] = sprintf(__('Downloading "%s"'), $downloadLink);
|
||||||
|
|
||||||
|
if ($tempFile = PluginsList :: download($downloadLink)) {
|
||||||
|
$this->view->log[] = sprintf(__('Unpacking "%s"'), $tempFile);
|
||||||
|
|
||||||
|
if (PluginsList :: install($tempFile, $slug)) {
|
||||||
|
CacheManager::clearObjectCache('vvveb', 'plugins_list_' . $this->global['site_id']);
|
||||||
|
$pluginName = \Vvveb\humanReadable($slug);
|
||||||
|
$pluginName = "<b>$pluginName</b>";
|
||||||
|
$pluginActivateUrl = \Vvveb\url(['module' => 'plugin/plugins', 'action'=> 'activate', 'plugin' => $slug]);
|
||||||
|
|
||||||
|
$successMessage = sprintf(__('Plugin %s was successfully updated!'), $pluginName, $pluginActivateUrl);
|
||||||
|
$this->view->log[] = $successMessage;
|
||||||
|
|
||||||
|
$this->view->success[] = $successMessage;
|
||||||
|
} else {
|
||||||
|
$error = sprintf(__('Error updating "%s"!'), $slug);
|
||||||
|
$this->view->log[] = $error;
|
||||||
|
$this->view->errors[] = $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink($tempFile);
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error downloading "%s" from %s!'), $slug, $downloadLink);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Plugin "%s" not found!'), $slug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$error = $e->getMessage();
|
||||||
|
$this->view->errors[] = $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->request->get['json'])) {
|
||||||
|
$this->view->setType('json');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deactivate() {
|
||||||
|
if (PluginsList::deactivate($this->plugin, $this->global['site_id'])) {
|
||||||
|
$this->view->success[] = sprintf(__('Plugin `%s` deactivated!'), '<b>' . \Vvveb\humanReadable($this->plugin) . '</b>');
|
||||||
|
CacheManager::clearObjectCache('admin-menu');
|
||||||
|
CacheManager::clearCompiledFiles();
|
||||||
|
CacheManager::clearPageCache();
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error deactivating plugin `%s`!'), '<b>' . \Vvveb\humanReadable($this->plugin) . '</b>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkPluginAndActivate() {
|
||||||
|
//allow plugin activation through get parameter if csrf is provided
|
||||||
|
if (($csrf = $this->request->get['csrf'] ?? false) &&
|
||||||
|
($plugin = $this->request->get['plugin'] ?? null) &&
|
||||||
|
($csrf == $this->session->get('csrf'))) {
|
||||||
|
$this->plugin = $plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->category = $this->request->get['category'] ?? false;
|
||||||
|
$this->pluginCheckUrl = \Vvveb\url(['module' => 'plugin/plugins', 'action'=> 'activate', 'plugin' => $this->plugin, 'category' => $this->category, 'csrf' => $this->session->get('csrf')]);
|
||||||
|
$this->view->checkPluginUrl = $this->pluginCheckUrl;
|
||||||
|
$this->view->info[] = sprintf(__('Activating %s plugin ...'), '<b>' . \Vvveb\humanReadable($this->plugin) . '</b> <span class="spinner-border spinner-border-sm align-middle" role="status" aria-hidden="true"></span>');
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
$view = View :: getInstance();
|
||||||
|
$view->category = $this->request->get['category'] ?? false;
|
||||||
|
$cache = (bool)($this->request->get['cache'] ?? true);
|
||||||
|
$view->plugins = PluginsList :: getList($this->global['site_id'], $view->category, $cache);
|
||||||
|
$view->categories = PluginsList :: getCategories($this->global['site_id']);
|
||||||
|
$view->safemode = ($admin = Admin::current()) && isset($admin['safemode']) && $admin['safemode'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete() {
|
||||||
|
if ($this->plugin) {
|
||||||
|
try {
|
||||||
|
if (PluginsList::uninstall($this->plugin, $this->global['site_id'])) {
|
||||||
|
$this->view->success[] = sprintf(__('Plugin "%s" removed!'), \Vvveb\humanReadable($this->plugin));
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error removing "%s" plugin!'), \Vvveb\humanReadable($this->plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//remove plugin public files if any
|
||||||
|
rrmdir(DIR_PUBLIC . DS . 'plugins' . DS . $this->plugin);
|
||||||
|
|
||||||
|
if (rrmdir(DIR_PLUGINS . $this->plugin)) {
|
||||||
|
$this->view->success[] = sprintf(__('Plugin "%s" removed!'), \Vvveb\humanReadable($this->plugin));
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = sprintf(__('Error removing "%s" plugin!'), \Vvveb\humanReadable($this->plugin));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->view->errors[] = sprintf(__('Error removing "%s" plugin!'), \Vvveb\humanReadable($this->plugin)) . ' - ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function upload() {
|
||||||
|
$files = $this->request->files;
|
||||||
|
$error = false;
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file && $file['error'] == UPLOAD_ERR_OK) {
|
||||||
|
try {
|
||||||
|
// use temorary file, php cleans temporary files on request finish.
|
||||||
|
$this->pluginSlug = PluginsList :: install($file['tmp_name'], str_replace('.zip', '', strtolower($file['name'])));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$error = $e->getMessage();
|
||||||
|
$this->view->errors[] = $error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$error = true;
|
||||||
|
$this->view->errors[] = sprintf(__('Error uploading %s!'), $file['name']);
|
||||||
|
$this->view->warning[] = sprintf(fileUploadErrMessage($file['error']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $error) {
|
||||||
|
if ($this->pluginSlug) {
|
||||||
|
$this->pluginName = \Vvveb\humanReadable($this->pluginSlug);
|
||||||
|
$this->pluginName = "<b>$this->pluginName</b>";
|
||||||
|
$this->pluginActivateUrl = \Vvveb\url(['module' => 'plugin/plugins', 'action'=> 'checkPluginAndActivate', 'plugin' => $this->pluginSlug, 'csrf' => $this->session->get('csrf')]);
|
||||||
|
$successMessage = sprintf(__('Plugin %s was successfully installed!'), $this->pluginName, $this->pluginActivateUrl);
|
||||||
|
$successMessage .= '<button type="submit" name="plugin" value="' . $this->themeSlug . '" class="btn btn-primary btn-sm ms-2" onclick="document.getElementById(\'action\').value=\'checkPluginAndActivate\';">' . __('Activate plugin') . '</button>';
|
||||||
|
$this->view->success[] = $successMessage;
|
||||||
|
} else {
|
||||||
|
$errorMessage = sprintf(__('Failed to install %s plugin!'), $this->pluginName);
|
||||||
|
$this->view->error[] = $errorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function activate() {
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
$this->category = $this->request->get['category'] ?? false;
|
||||||
|
$this->plugin = $this->request->post['plugin'] ?? $this->request->get['plugin'] ?? null;
|
||||||
|
$csrf = $this->request->post['csrf'] ?? $this->request->get['csrf'] ?? false;
|
||||||
|
|
||||||
|
if (! defined('CLI') && $csrf != $this->session->get('csrf')) {
|
||||||
|
die('Invalid csrf!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$active = false;
|
||||||
|
$error = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (PluginsList::loadPlugin($this->plugin)) {
|
||||||
|
if (PluginsList::activate($this->plugin, $this->global['site_id'])) {
|
||||||
|
$active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\ParseError $e) {
|
||||||
|
$error = exceptionToArray($e);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$error = exceptionToArray($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
$error['minimal'] = true;
|
||||||
|
$error['title'] = sprintf(__('Error activating plugin `%s`!'), $this->plugin);
|
||||||
|
FrontController::notFound(false, $error, 500);
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($active) {
|
||||||
|
$refreshUrl = \Vvveb\url(['module' => 'plugin/plugins', 'cache' => false, 'category' => $this->category], false) . '&t=' . time();
|
||||||
|
$success = sprintf(__('Plugin `%s` activated!'), '<b>' . \Vvveb\humanReadable($this->plugin) . '</b>');
|
||||||
|
$plugin = PluginsList :: getList($this->global['site_id'])[$this->plugin] ?? [];
|
||||||
|
|
||||||
|
if (isset($plugin['settings']) && $plugin['settings']) {
|
||||||
|
$success .= "<a class='btn btn-primary btn-sm m-2' href='{$plugin['settings']}'>" . __('Settings') . '</a>';
|
||||||
|
}
|
||||||
|
$this->session->set('success', $success);
|
||||||
|
|
||||||
|
ignore_user_abort(1);
|
||||||
|
clearstatcache(true);
|
||||||
|
|
||||||
|
CacheManager::clearObjectCache('admin-menu');
|
||||||
|
CacheManager::clearCompiledFiles();
|
||||||
|
CacheManager::clearPageCache();
|
||||||
|
|
||||||
|
if (defined('CLI')) {
|
||||||
|
$this->view->success = [$success];
|
||||||
|
} else {
|
||||||
|
$response = "
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
function reloadPage() {
|
||||||
|
//setTimeout(() => parent.location='$refreshUrl&success=$success', 100);
|
||||||
|
setTimeout(() => parent.location='$refreshUrl', 100);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload='reloadPage()'><!-- Plugin valid -->
|
||||||
|
</body>
|
||||||
|
</html>";
|
||||||
|
|
||||||
|
die($response);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die(sprintf(__('Error activating plugin `%s`!'), $this->plugin) . '<br/>' . __('Check config file permissions!'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
110
admin/controller/product/attribute-group.php
Normal file
110
admin/controller/product/attribute-group.php
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use Vvveb\Sql\Attribute_GroupSQL;
|
||||||
|
use Vvveb\Sql\AttributeSQL;
|
||||||
|
|
||||||
|
class AttributeGroup extends Crud {
|
||||||
|
protected $type = 'attribute_group';
|
||||||
|
|
||||||
|
protected $controller = 'attribute-group';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$this->redirect = false;
|
||||||
|
parent::save();
|
||||||
|
|
||||||
|
$delete = $this->request->post['delete']['attribute_id'] ?? [];
|
||||||
|
$attribute = $this->request->post['attribute'] ?? [];
|
||||||
|
$attribute_group = $this->request->post['attribute_group'] ?? [];
|
||||||
|
$edit = $this->request->get['attribute_group_id'] ?? false;
|
||||||
|
$attribute_group_id = $this->attribute_group_id;
|
||||||
|
$new = [];
|
||||||
|
|
||||||
|
foreach ($attribute as $index => &$attr) {
|
||||||
|
$attr['attribute_group_id'] = $attribute_group_id;
|
||||||
|
$attr['sort_order'] = $attr['sort_order'] ?? 0;
|
||||||
|
|
||||||
|
if (! $attr['attribute_id'] && $attr['name']) {
|
||||||
|
unset($attr['attribute_id']);
|
||||||
|
$new[] = $attr;
|
||||||
|
unset($attribute[$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($attribute_group_id) {
|
||||||
|
$attributeGroup = new Attribute_GroupSQL();
|
||||||
|
$attributeSql = new AttributeSQL();
|
||||||
|
|
||||||
|
if ($delete) {
|
||||||
|
$attributeSql->delete(['attribute_id' => $delete] + $this->global);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($attribute) {
|
||||||
|
foreach ($attribute as $index => &$attr) {
|
||||||
|
$attributeSql->edit(['attribute' => $attr, 'attribute_id' => $attr['attribute_id']] + $this->global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($new) {
|
||||||
|
foreach ($new as $index => &$attr) {
|
||||||
|
$attributeSql->add(['attribute' => $attr] + $this->global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $attributeGroup->edit(['attribute_group_id' => $attribute_group_id, 'attribute_group' => $attribute_group]);
|
||||||
|
|
||||||
|
if ($result && isset($result['attribute_group_content'])) {
|
||||||
|
if (! $edit) {
|
||||||
|
$this->redirect(['module' => "{$this->module}/{$this->controller}", 'attribute_group_id' => $attribute_group_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$successMessage = __('Saved!');
|
||||||
|
$this->view->success['get'] = $successMessage;
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
$attribute_group_id = $this->request->get['attribute_group_id'] ?? false;
|
||||||
|
|
||||||
|
$attributes = [];
|
||||||
|
|
||||||
|
if ($attribute_group_id) {
|
||||||
|
$attributeGroup = new AttributeSQL();
|
||||||
|
$attributes = $attributeGroup->getAll(['attribute_group_id' => $attribute_group_id, 'limit' => 1000] + $this->global)['attribute'] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->attributes = $attributes;
|
||||||
|
$this->view->attribute_group_id = $attribute_group_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
admin/controller/product/attribute-groups.php
Normal file
39
admin/controller/product/attribute-groups.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class AttributeGroups extends Listing {
|
||||||
|
protected $additionalPermissionCheck = ['product/attribute-group/save'];
|
||||||
|
|
||||||
|
protected $type = 'attribute_group';
|
||||||
|
|
||||||
|
protected $controller = 'attribute-group';
|
||||||
|
|
||||||
|
protected $listController = 'attribute-groups';
|
||||||
|
|
||||||
|
protected $list = 'attribute_group';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
}
|
||||||
33
admin/controller/product/attribute.php
Normal file
33
admin/controller/product/attribute.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
|
||||||
|
class Attribute extends Crud {
|
||||||
|
protected $type = 'attribute';
|
||||||
|
|
||||||
|
protected $controller = 'attribute';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
}
|
||||||
39
admin/controller/product/attributes.php
Normal file
39
admin/controller/product/attributes.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Attributes extends Listing {
|
||||||
|
protected $additionalPermissionCheck = ['product/attribute/save'];
|
||||||
|
|
||||||
|
protected $type = 'attribute';
|
||||||
|
|
||||||
|
protected $controller = 'attribute';
|
||||||
|
|
||||||
|
protected $listController = 'attributes';
|
||||||
|
|
||||||
|
protected $list = 'attribute';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
}
|
||||||
28
admin/controller/product/categories.php
Normal file
28
admin/controller/product/categories.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Content\Categories as ContentCategories;
|
||||||
|
|
||||||
|
class Categories extends ContentCategories {
|
||||||
|
}
|
||||||
53
admin/controller/product/digital-asset.php
Normal file
53
admin/controller/product/digital-asset.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
use Vvveb\System\Traits\Media as MediaTrait;
|
||||||
|
|
||||||
|
class DigitalAsset extends Crud {
|
||||||
|
use MediaTrait;
|
||||||
|
|
||||||
|
protected $dirMedia = DIR_STORAGE . 'digital_assets';
|
||||||
|
|
||||||
|
protected $type = 'digital_asset';
|
||||||
|
|
||||||
|
protected $controller = 'digital-asset';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
|
||||||
|
$adminPath = \Vvveb\adminPath();
|
||||||
|
|
||||||
|
$controllerPath = $adminPath . 'index.php?module=product/digital-asset';
|
||||||
|
$this->setMediaEndpoints($controllerPath);
|
||||||
|
|
||||||
|
if ($this->view->digital_asset) {
|
||||||
|
$this->view->digital_asset['image'] = $this->view->digital_asset['file'];
|
||||||
|
$this->view->digital_asset['image_url'] = Images::image($this->view->digital_asset['image'], 'digital_asset', 'thumb');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
admin/controller/product/digital-assets.php
Normal file
39
admin/controller/product/digital-assets.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class DigitalAssets extends Listing {
|
||||||
|
protected $additionalPermissionCheck = ['product/digital-asset/save'];
|
||||||
|
|
||||||
|
protected $type = 'digital_asset';
|
||||||
|
|
||||||
|
protected $controller = 'digital-asset';
|
||||||
|
|
||||||
|
protected $listController = 'digital-assets';
|
||||||
|
|
||||||
|
protected $list = 'digital_asset';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
}
|
||||||
31
admin/controller/product/manufacturer.php
Normal file
31
admin/controller/product/manufacturer.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
|
||||||
|
class Manufacturer extends Crud {
|
||||||
|
protected $type = 'manufacturer';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
}
|
||||||
33
admin/controller/product/manufacturers.php
Normal file
33
admin/controller/product/manufacturers.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Manufacturers extends Listing {
|
||||||
|
protected $type = 'manufacturer';
|
||||||
|
|
||||||
|
protected $list = 'manufacturer';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
}
|
||||||
128
admin/controller/product/option.php
Normal file
128
admin/controller/product/option.php
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use function Vvveb\__;
|
||||||
|
use Vvveb\Controller\Crud;
|
||||||
|
use Vvveb\Sql\Option_ValueSQL;
|
||||||
|
use Vvveb\Sql\OptionSQL;
|
||||||
|
use Vvveb\System\Images;
|
||||||
|
|
||||||
|
class Option extends Crud {
|
||||||
|
protected $type = 'option';
|
||||||
|
|
||||||
|
protected $controller = 'option';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
$this->redirect = false;
|
||||||
|
parent::save();
|
||||||
|
|
||||||
|
$delete = $this->request->post['delete']['option_value_id'] ?? [];
|
||||||
|
$option_value = $this->request->post['option_value'] ?? [];
|
||||||
|
$option = $this->request->post['option'] ?? [];
|
||||||
|
$edit = $this->request->get['option_id'] ?? false;
|
||||||
|
$option_id = $this->option_id;
|
||||||
|
$new = [];
|
||||||
|
|
||||||
|
foreach ($option_value as $index => &$attr) {
|
||||||
|
$attr['option_id'] = $option_id;
|
||||||
|
$attr['sort_order'] = $attr['sort_order'] ?? 0;
|
||||||
|
|
||||||
|
if (! $attr['option_value_id'] && $attr['name']) {
|
||||||
|
unset($attr['option_value_id']);
|
||||||
|
$new[] = $attr;
|
||||||
|
unset($option_value[$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($option_id) {
|
||||||
|
$optionSql = new OptionSQL();
|
||||||
|
$option_valueSql = new Option_ValueSQL();
|
||||||
|
|
||||||
|
if ($delete) {
|
||||||
|
$option_valueSql->delete(['option_value_id' => $delete] + $this->global);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($option_value) {
|
||||||
|
foreach ($option_value as $index => &$attr) {
|
||||||
|
$option_valueSql->edit(['option_value' => $attr, 'option_value_id' => $attr['option_value_id']] + $this->global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($new) {
|
||||||
|
foreach ($new as $index => &$attr) {
|
||||||
|
$option_valueSql->add(['option_value' => $attr] + $this->global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $optionSql->edit(['option_id' => $option_id, 'option' => $option]);
|
||||||
|
|
||||||
|
if ($result && isset($result['option_content'])) {
|
||||||
|
if (! $edit) {
|
||||||
|
$this->redirect(['module' => "{$this->module}/{$this->controller}", 'option_id' => $option_id]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->view->errors[] = __('Error saving!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
parent::index();
|
||||||
|
$option_id = $this->request->get['option_id'] ?? false;
|
||||||
|
|
||||||
|
$option_values = [];
|
||||||
|
|
||||||
|
if ($option_id) {
|
||||||
|
$option_valueGroup = new Option_ValueSQL();
|
||||||
|
$option_values = $option_valueGroup->getAll(['option_id' => $option_id, 'limit' => 1000] + $this->global)['option_value'] ?? [];
|
||||||
|
|
||||||
|
foreach ($option_values as &$value) {
|
||||||
|
$value['image_url'] = Images::image($value['image'], 'product', 'thumb');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->type = [
|
||||||
|
'text' => 'Text',
|
||||||
|
'number' => 'Number',
|
||||||
|
'textarea'=> 'Textarea',
|
||||||
|
'email' => 'Email',
|
||||||
|
'select' => 'Select',
|
||||||
|
'radio' => 'Radio',
|
||||||
|
'checkbox'=> 'Checkbox',
|
||||||
|
'select' => 'Select',
|
||||||
|
'image' => 'Image',
|
||||||
|
'date' => 'Date',
|
||||||
|
'time' => 'Time',
|
||||||
|
'datetime'=> 'Date time',
|
||||||
|
'file' => 'File',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->view->option_values = $option_values;
|
||||||
|
$this->view->option_id = $option_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
admin/controller/product/options.php
Normal file
39
admin/controller/product/options.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Listing;
|
||||||
|
|
||||||
|
class Options extends Listing {
|
||||||
|
protected $additionalPermissionCheck = ['product/option/save'];
|
||||||
|
|
||||||
|
protected $type = 'option';
|
||||||
|
|
||||||
|
protected $controller = 'option';
|
||||||
|
|
||||||
|
protected $listController = 'options';
|
||||||
|
|
||||||
|
protected $list = 'option';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
}
|
||||||
35
admin/controller/product/product-question.php
Normal file
35
admin/controller/product/product-question.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Content\Comment;
|
||||||
|
|
||||||
|
class Productquestion extends Comment {
|
||||||
|
protected $type = 'product_question';
|
||||||
|
|
||||||
|
protected $list = 'product_question';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
|
||||||
|
protected $controller = 'product-question';
|
||||||
|
}
|
||||||
37
admin/controller/product/product-questions.php
Normal file
37
admin/controller/product/product-questions.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Content\Comments;
|
||||||
|
|
||||||
|
class ProductQuestions extends Comments {
|
||||||
|
protected $type = 'product_question';
|
||||||
|
|
||||||
|
protected $list = 'product_question';
|
||||||
|
|
||||||
|
protected $listController = 'product-questions';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
|
||||||
|
protected $controller = 'product-question';
|
||||||
|
}
|
||||||
35
admin/controller/product/product-review.php
Normal file
35
admin/controller/product/product-review.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vvveb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Ziadin Givan
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vvveb\Controller\Product;
|
||||||
|
|
||||||
|
use Vvveb\Controller\Content\Comment;
|
||||||
|
|
||||||
|
class ProductReview extends Comment {
|
||||||
|
protected $type = 'product_review';
|
||||||
|
|
||||||
|
protected $list = 'product_review';
|
||||||
|
|
||||||
|
protected $module = 'product';
|
||||||
|
|
||||||
|
protected $controller = 'product-review';
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user