From 74f1c04022328280b996dde0b7089e13d96acf70 Mon Sep 17 00:00:00 2001 From: George Halkiadakis Date: Sat, 22 Apr 2023 13:15:14 +0300 Subject: edit lesson: media handling --- Dockerfile | 5 +- core/classes/Request.php | 8 +- core/config/anom_settings.php | 2 + docker-compose.yml | 1 + docker/bin/docker-entrypoint.sh | 2 + public/app/config/app_constants.php | 3 +- public/app/controllers/admin/Course_admin.php | 136 ++++++++++++++++++++++++++ public/app/routes/backend.php | 25 +++-- public/app/views/admin/categories.php | 10 +- public/app/views/admin/edit_lesson.php | 12 ++- public/assets/css/overides.css | 4 +- public/assets/js/admin/categories.js | 2 +- public/assets/js/admin/edit_lesson.js | 45 ++++----- public/files/.gitkeep | 0 tests/abstract.php | 0 tests/algo-hashes.php | 0 tests/auth.php | 0 tests/code/abstract.php | 0 tests/code/bits.php | 0 tests/code/echo.php | 0 tests/code/exceptions.php | 0 tests/code/interface.php | 0 tests/code/login.php | 0 tests/code/proxy.php | 0 tests/code/session.php | 0 tests/code/str-replace.php | 0 tests/compare/compress.php | 0 tests/compare/hashcost.php | 0 tests/compare/md5-v-sha1.php | 0 tests/compare/memcached-v-filecache.php | 0 tests/compare/redis-v-filecache.php | 0 tests/compare/serialize-v-jsonencode.php | 0 tests/compare/sha1-v-sha256.php | 0 tests/dotnet-pass.php | 0 tests/mail.php | 0 tests/php.php | 0 tests/repository.php | 0 tests/service/entropy.php | 0 tests/service/memcached.php | 0 tests/service/redis.php | 0 tests/userman.php | 0 41 files changed, 210 insertions(+), 45 deletions(-) create mode 100644 public/files/.gitkeep mode change 100644 => 100755 tests/abstract.php mode change 100644 => 100755 tests/algo-hashes.php mode change 100644 => 100755 tests/auth.php mode change 100644 => 100755 tests/code/abstract.php mode change 100644 => 100755 tests/code/bits.php mode change 100644 => 100755 tests/code/echo.php mode change 100644 => 100755 tests/code/exceptions.php mode change 100644 => 100755 tests/code/interface.php mode change 100644 => 100755 tests/code/login.php mode change 100644 => 100755 tests/code/proxy.php mode change 100644 => 100755 tests/code/session.php mode change 100644 => 100755 tests/code/str-replace.php mode change 100644 => 100755 tests/compare/compress.php mode change 100644 => 100755 tests/compare/hashcost.php mode change 100644 => 100755 tests/compare/md5-v-sha1.php mode change 100644 => 100755 tests/compare/memcached-v-filecache.php mode change 100644 => 100755 tests/compare/redis-v-filecache.php mode change 100644 => 100755 tests/compare/serialize-v-jsonencode.php mode change 100644 => 100755 tests/compare/sha1-v-sha256.php mode change 100644 => 100755 tests/dotnet-pass.php mode change 100644 => 100755 tests/mail.php mode change 100644 => 100755 tests/php.php mode change 100644 => 100755 tests/repository.php mode change 100644 => 100755 tests/service/entropy.php mode change 100644 => 100755 tests/service/memcached.php mode change 100644 => 100755 tests/service/redis.php mode change 100644 => 100755 tests/userman.php diff --git a/Dockerfile b/Dockerfile index 6e76571..adb4c79 100644 --- a/Dockerfile +++ b/Dockerfile @@ -75,12 +75,13 @@ RUN sed -i 's/^# *\(el_GR\)/\1/' /etc/locale.gen RUN locale-gen -# Manage permitions in specific directories +# Manage permitions in specific (writable) directories # ------------------------------------------------------------------------------ # (make local storage directories writable) RUN chown -R www-data:www-data /var/www RUN chmod -R 757 /var/www/storage - +RUN chown -R www-data:www-data /var/www/public/files +RUN chmod -R 757 /var/www/public/files # change apache's default-root to /var/www/public RUN sed -ri -e 's!/var/www/html!/var/www/public!g' /etc/apache2/sites-available/*.conf diff --git a/core/classes/Request.php b/core/classes/Request.php index bc322a1..89928f9 100644 --- a/core/classes/Request.php +++ b/core/classes/Request.php @@ -21,9 +21,11 @@ class Request public $AGENT; // Client's User Agent - public $GET = []; + public $GET = []; // $_GET array - public $POST = []; + public $POST = []; // $_POST array + + public $FILES = []; // $_FILES array public $SIGNATURE; // user/client's device signature @@ -48,6 +50,8 @@ class Request // * If (for any reason) you requide $_GET sanitization // enable it later on the method's code + $this->FILES = $_FILES; // TODO: sanitize the files array + // $this->INTERFACE = php_sapi_name(); $this->AGENT = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'; diff --git a/core/config/anom_settings.php b/core/config/anom_settings.php index f6e7236..50056bf 100644 --- a/core/config/anom_settings.php +++ b/core/config/anom_settings.php @@ -161,6 +161,8 @@ define('CACHE_PRODUCT_TTL', 3600); // 1 hour define('FILECACHE_PATH', APP_ROOT.'/../storage/cache/'); // if CACHE_DRIVER is set to 'FileCache' +define('MEDIA_STORAGE_ROOT', APP_ROOT.'/../storage/uploads/'); // Media files root directory + # define('REDIS_HOST', '127.0.0.1'); // if CACHE_DRIVER is set to 'RedisCache' # define('MEMCAHCED_SERVER', '127.0.0.1'); // if CACHE_DRIVER is set to 'MemCached' diff --git a/docker-compose.yml b/docker-compose.yml index bdc203d..adf7b7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,7 @@ services: - "./docker:/var/www/docker" - "./storage:/var/www/storage" - "./tests:/var/www/tests" + - "./tests:/var/www/public/files" environment: PORT: 8080 # for xdebug uncomment next subsection diff --git a/docker/bin/docker-entrypoint.sh b/docker/bin/docker-entrypoint.sh index f421d80..edcce41 100644 --- a/docker/bin/docker-entrypoint.sh +++ b/docker/bin/docker-entrypoint.sh @@ -6,6 +6,8 @@ # set file-cache directory to apache's user ownership chmod -R 755 /var/www/storage chown -R www-data:www-data /var/www/storage +chown -R www-data:www-data /var/www/public/files +chmod -R 757 /var/www/public/files # copy composer.json to 'www'; then prepare auutoloading # ------------------------------------------------------------------------------ diff --git a/public/app/config/app_constants.php b/public/app/config/app_constants.php index 0d04dc2..529d04a 100644 --- a/public/app/config/app_constants.php +++ b/public/app/config/app_constants.php @@ -4,7 +4,7 @@ // Default Values (user-privileges and user-roles) -// read ini file id exist +// read ini file if exist // --- -- -- - - - if (file_exists("../core/auth/.env")) { $env = parse_ini_file("../core/auth/.env"); @@ -12,6 +12,7 @@ if (file_exists("../core/auth/.env")) { + // CENTRAL DEFAULTS //////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- diff --git a/public/app/controllers/admin/Course_admin.php b/public/app/controllers/admin/Course_admin.php index 0e34e00..ef9ef0e 100644 --- a/public/app/controllers/admin/Course_admin.php +++ b/public/app/controllers/admin/Course_admin.php @@ -9,6 +9,13 @@ use app\models\cms\Course_model; class Course_admin { + ## ------------------------------------------------------------------------- + ## + ## COURSE (category) METHODS + ## + ## ------------------------------------------------------------------------- + + /** breadcrumbs * --- * responds to ajax GET: /admin/api/categories @@ -90,4 +97,133 @@ class Course_admin { ]; } + + + + ## ------------------------------------------------------------------------- + ## + ## FILE METHODS + ## + ## ------------------------------------------------------------------------- + + + /** upload_file + * upload the file to the file system + * + * the method reads the POST and FILES array + * to retrieve all needed parametres + * + * + $_FILES[file] + * + $_POST[folder] : lesson's ID + * + $_POST[reference] : reference type + */ + public static function upload_file() + { + $post = Registry::get('REQUEST')->POST; + $files = Registry::get('REQUEST')->FILES; + + + // Checks before uploading the file + //////////////////////////////////////////////////////////////////////// + + // ** 1: file is upladed to temporary folder --------------------------- + if (! is_uploaded_file($files['file']['tmp_name'])) { + return ['success' => false]; // bye! + } + + // ** 2: File belongs to the allowed MIME types ------------------------ + $allowed_file_types = array( + 'application/pdf', + 'image/png', 'image/jpeg', + 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + ); + // Recomended MIME type checking via mime_content_type(): + $mime_type = mime_content_type($files['file']['tmp_name']); + if (! in_array($mime_type, $allowed_file_types)) { // File type NOT allowed ... + return ['success' => false]; // bye! + } + + $file_name = $files['file']['name']; + $file_type = $files['file']['type']; // do not take it for granted + $file_size = $files['file']['size']; + $file_tmp = $files['file']['tmp_name']; + + $bare_name = pathinfo($file_name, PATHINFO_FILENAME); + $file_ext = pathinfo($file_name, PATHINFO_EXTENSION); + + + // ** 3: filename or size checks may be added -------------------------- + if ($file_name == "") { + return ['success' => false]; // bye! + } + + + // READY to finaly save/upload the file to CDN ///////////////////////// + + $folder = MEDIA_STORAGE_ROOT . $post['folder']; + if (!file_exists($folder)) { // create folder if not exists + mkdir($folder, 0757, true); + } + + // print_r([ + // 'dir' => $folder, + // 'file' => $bare_name, + // 'ext' => $file_ext, + // 'type' => $file_type + // ]); die(); + + $relative_filename = $post['folder'] + .'/' + . strtolower(self::clear_file_name($bare_name) .'.'. $file_ext); + $store_filename = MEDIA_STORAGE_ROOT . $relative_filename; + + if (move_uploaded_file($files["file"]["tmp_name"], $store_filename)) { + return [ + 'success' => true, + 'path' => $store_filename, + 'type' => $mime_type + ]; + + } else { return ['success' => false]; } + + } + + + /** clear_file_name + * replace greek characters and strip symbols + */ + private static function clear_file_name($str) + { + $el = mb_split( "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωάέήίόύώϊϋς ", ""); + $en = str_split("ABGDEZHUIKLMNJOPRSTYFXCVabgdezhuiklmnjoprstyfxcvaehioyviys-"); + $strip = str_split("!@#$%^&*()+~`[]{};'/<>?=\""); + + return str_replace($strip, '', str_replace($el, $en, $str)); + } + + + /** define_media + * + * create a record in media table + * + * @param $data + * @return id (int): id of created media record + */ + public static function define_media($data) + { + $sql = "INSERT INTO wiki_media (`title`, `type`, `path`) + VALUES (:title, :mimetype, :filepath)"; + $stmt = $this->pdo->prepare($sql); + $stmt->execute([ + 'title' => $data['title'], + 'mimetype' => $data['type'], + 'filepath' => $data['path'] + ]); + $inserted_id = $this->pdo->lastInsertId(); + + return $inserted_id; + } + + } \ No newline at end of file diff --git a/public/app/routes/backend.php b/public/app/routes/backend.php index 88bf4b8..704d161 100644 --- a/public/app/routes/backend.php +++ b/public/app/routes/backend.php @@ -15,7 +15,7 @@ Route::add('/admin/lessons', function () { }); -// admin cateogies +// admin categories (=courses) // ----------------------------------------------------------------------------- // manage categories page @@ -23,7 +23,7 @@ Route::add('/admin/lessons', function () { Route::add('/admin/categories', function () { Auth::allowRoles([1, 2, 3]); Render::view('admin/skeleton', [ - 'title' => 'Διαχείριση Κατηγοριών', + 'title' => 'Διαχείριση Κεφαλαίων', 'action' => 'categories', ]); }); @@ -39,16 +39,14 @@ Route::add('/admin/api/categories', function () { // ajax: add new category (course) // --- -Route::add('/admin/api/category/add', function () { - Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles - Course_admin::add_course(); - }, - 'post' -); +Route::add('/admin/api/categories/add', function () { + Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles + Course_admin::add_course(); +}, 'post'); // ajax: edit category (course) // --- -Route::add('/admin/api/category/update', function () { +Route::add('/admin/api/categories/update', function () { Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles Course_admin::update_course(); }, @@ -106,3 +104,12 @@ Route::add('/admin/edit_lesson/([0-9]*)', function ($id) { 'id' => intval($id) ]); }); + + + +// ajax: file-upload +// --- +Route::add('/admin/api/file_upload', function () { + Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles + Render::json(Course_admin::upload_file()); +}, 'post'); diff --git a/public/app/views/admin/categories.php b/public/app/views/admin/categories.php index 91acec1..26fd5a2 100644 --- a/public/app/views/admin/categories.php +++ b/public/app/views/admin/categories.php @@ -5,7 +5,7 @@ @@ -18,7 +18,7 @@ - +
ΚατηγορίαΚατηγορία/Κεφάλαιο
@@ -72,12 +72,12 @@