From e6057d0b3f6d717826c1ff150b8593cb807c231f Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:12:40 +0200 Subject: [PATCH 1/9] minor: CSS adding styles for button loading --- main/css/base.css | 220 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 212 insertions(+), 8 deletions(-) diff --git a/main/css/base.css b/main/css/base.css index 5419c925b7..65d034282c 100644 --- a/main/css/base.css +++ b/main/css/base.css @@ -3978,6 +3978,21 @@ footer { box-shadow:none; } +.btn.loading{ + border:none; + border-radius: 0; + background-color: transparent; + width:22px; + height:22px; + margin:0; + padding:0; + display:inline-block; + background-image: url('../img/loading1.gif') !important; + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + .announce.btn.delete-all{ border:none; border-radius: 0; @@ -4038,6 +4053,36 @@ footer { box-shadow:none; } +.btn.import_csv{ + border:none; + border-radius: 0; + background-color: transparent; + width:32px; + height:32px; + margin:0; + padding:0; + display:inline-block; + background-image: url('../img/icons/32/import_csv.png'); + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + +.btn.delete_all{ + border:none; + border-radius: 0; + background-color: transparent; + width:32px; + height:32px; + margin:0; + padding:0; + display:inline-block; + background-image: url('../img/icons/32/delete.png'); + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + .btn.expand{ border:none; border-radius: 0; @@ -4068,7 +4113,7 @@ footer { box-shadow:none; } -.announce.btn.new{ +.btn.back{ border:none; border-radius: 0; background-color: transparent; @@ -4077,12 +4122,13 @@ footer { margin:0; padding:0; display:inline-block; - background-image: url('../img/icons/32/new_announce.png'); + background-image: url('../img/icons/32/back.png'); background-repeat: no-repeat; background-position:center center; box-shadow:none; } -.announce.btn.back{ + +.btn.view.detailed{ border:none; border-radius: 0; background-color: transparent; @@ -4091,14 +4137,44 @@ footer { margin:0; padding:0; display:inline-block; - background-image: url('../img/icons/32/back.png'); + background-image: url('../img/icons/32/view_detailed.png'); + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + +.btn.view.text{ + border:none; + border-radius: 0; + background-color: transparent; + width:32px; + height:32px; + margin:0; + padding:0; + display:inline-block; + background-image: url('../img/icons/32/view_text.png'); + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + +.announce.btn.new{ + border:none; + border-radius: 0; + background-color: transparent; + width:32px; + height:32px; + margin:0; + padding:0; + display:inline-block; + background-image: url('../img/icons/32/new_announce.png'); background-repeat: no-repeat; background-position:center center; box-shadow:none; } .announcement { -/* background: none repeat scroll 0 0 #F2F2F2;*/ + /* background: none repeat scroll 0 0 #F2F2F2;*/ border: 1px solid #D3D3D3; color: #555555; font-weight: normal; @@ -4109,8 +4185,8 @@ footer { width: 100%; } .announcement .title{ - background: none repeat scroll 0 0 #F2F2F2; - color:black; + background: none repeat scroll 0 0 #F2F2F2; + color:black; } .announcement .title a:link, @@ -4152,6 +4228,10 @@ li.annoucement{ cursor: pointer; } +/* + link +*/ + .link_category{ background-color: #FFFFFF; margin-bottom: 5px; @@ -4225,6 +4305,63 @@ li.annoucement{ color: #999999; } +.link .status{ + border:none; + border-radius: 0; + background-color: transparent; + width:22px; + height:22px; + margin:0; + padding:0; + display:inline-block; + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + +.link.invalid .status{ + background-image: url('../img/icons/22/error.png'); +} + +.link.valid .status{ + background-image: url('../img/icons/22/accept.png'); +} + +.btn.validate_link{ + border:none; + border-radius: 0; + background-color: transparent; + width:22px; + height:22px; + margin:0; + padding:0; + display:inline-block; + background-image: url('../img/icons/22/preview_view.png'); + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + +/* + Glossary +*/ + +.glossary.btn.new.term{ + border:none; + border-radius: 0; + background-color: transparent; + width:32px; + height:32px; + margin:0; + padding:0; + display:inline-block; + background-image: url('../img/icons/32/new_glossary_term.png'); + background-repeat: no-repeat; + background-position:center center; + box-shadow:none; +} + + #learning_path_main #control { text-align: center; background-image:-webkit-gradient(linear,left top,left bottom,from(#ececec),to(#fff)); @@ -4233,7 +4370,7 @@ li.annoucement{ background-image:-ms-linear-gradient(top,#ececec,#fff); background-image:-o-linear-gradient(top,#ececec,#fff); background-image:linear-gradient(top,#ececec,#fff); - + height:32px; padding:8px 0px 8px 0px; opacity:0.9; @@ -4245,6 +4382,73 @@ li.annoucement{ } +/* +data table +*/ + +.dataTables_wrapper{ + clear: both; +} + +.dataTables_length { + float: left; + width: 40%; +} + +.dataTables_filter { + text-align: right; +} + +.dataTables_info { + float: left; + width: 60%; +} + +.dataTables_paginate { + float: right; + text-align: right; +} + +.dataTables_wrapper label input, .dataTables_wrapper label textarea, .dataTables_wrapper label select { + display: inline-block; +} + +.dataTables.display { + clear: both; + margin: 0 auto; + width: 100%; +} + +.dataTables_wrapper .paginate_disabled_previous, .dataTables_wrapper .paginate_enabled_previous { + padding-left: 23px; + background: url("../img/action_prev.png") no-repeat scroll left top; +} + +.dataTables_wrapper .paginate_disabled_next, .dataTables_wrapper .paginate_enabled_next { + margin-left: 10px; + padding-right: 23px; + background: url("../img/action_next.png") no-repeat scroll left top; +} + +.dataTables_wrapper .paginate_disabled_previous, .dataTables_wrapper .paginate_disabled_next{ + opacity: 0.4; +} + +.dataTables_wrapper .sorting_asc { + background-image: url("../img/sort_asc.png"); + background-repeat: no-repeat; + background-attachment: scroll; + background-position: right center; +} + +.dataTables_wrapper .sorting_desc{ + background-image: url("../img/sort_desc.png"); + background-repeat: no-repeat; + background-attachment: scroll; + background-position: right center; +} + + #course_category_well { padding: 9px 0; } From 9bfe05322ac3e689d6d365de348d26732ba6a150 Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:14:21 +0200 Subject: [PATCH 2/9] minor: exposes allows get_property to be called as usual (quite useful for twig) --- main/inc/lib/entity.class.php | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/main/inc/lib/entity.class.php b/main/inc/lib/entity.class.php index 15cbc1fc9d..43b0645b9f 100644 --- a/main/inc/lib/entity.class.php +++ b/main/inc/lib/entity.class.php @@ -41,11 +41,39 @@ class Entity return $result; } - public function __construct() + function __construct($data = null) { + if ($data) { + foreach ($this as $key => $value) { + if (isset($data->{$key})) { + $this->{$key} = $data->{$key}; + } + } + } $this->defaults('session_id', api_get_session_id()); } + function __get($name) + { + $f = array($this, "get_$name"); + return call_user_func($f); + } + + function __isset($name) + { + $f = array($this, "get_$name"); + return is_callable($f); + } + + function __set($name, $value) + { + $f = array($this, "set_$name"); + if (!is_callable($f)) { + return; + } + call_user_func($f, $value); + } + function before_save() { $repo = $this->repository(); From dd55e0ab63c89abe3ec3f4b151cec09a789eb6a2 Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:14:53 +0200 Subject: [PATCH 3/9] minor: add a base controller and access to be derived from --- main/inc/lib/access.class.php | 203 ++++++++++++++++++++++++++++++ main/inc/lib/controller.class.php | 198 +++++++++++++++++++++++++++++ 2 files changed, 401 insertions(+) create mode 100644 main/inc/lib/access.class.php create mode 100644 main/inc/lib/controller.class.php diff --git a/main/inc/lib/access.class.php b/main/inc/lib/access.class.php new file mode 100644 index 0000000000..8d05042e26 --- /dev/null +++ b/main/inc/lib/access.class.php @@ -0,0 +1,203 @@ + for the Univesity of Geneva + * @license /license.txt + */ +abstract class Access +{ + + const SEC_TOKEN = 'sec_token'; + + /** + * Return view and edit access. + * + * @return \Access + */ + public static function all() + { + return AccessAll::instance(); + } + + /** + * Return no access. + * + * @return \Access + */ + public static function forbidden() + { + AccessForbidden::instance(); + } + + protected $session_token; + protected $token; + + /** + * Returns true if security token is valid, false otherwise. + * + * @return bool + */ + public function is_token_valid() + { + $call_token = Request::get_security_token(); + if (empty($call_token)) { + return false; + } + $session_token = $this->get_session_token(); + return $session_token == $call_token; + } + + /** + * Returns the token contained in the session. + * Stores the token for further reuse so that it can be changed in session. + * + * @return string + */ + public function get_session_token() + { + if (empty($this->session_token)) { + $key = self::SEC_TOKEN; + $this->session_token = isset($_SESSION[$key]) ? $_SESSION[$key] : ''; + } + return $this->session_token; + } + + /* + * On first call generate a new security token and save it in session. + * On successful calls returns the same (new) token (function is repeatable). + * If user do not have the right to edit, returns a blank (invalid) token. + * + * Stores the existing session token before saving the new one so that + * the current call can still be validated after calling this function. + */ + + public function get_token() + { + if (!$this->can_edit()) { + return ''; + } + if ($this->token) { + return $this->token; + } + $this->session_token = $this->get_session_token(); + + + $this->token = \Security::get_token(); + } + + /** + * Returns true if the user has the right to edit. + * + * @return boolean + */ + public abstract function can_edit(); + + /** + * Returns true if the current user has the right to view + * + * @return boolean + */ + public abstract function can_view(); + + public function authorize() + { + return $this->can_view(); + } + +} + +/** + * Authorize access and view access. + */ +class AccessAll extends Access +{ + + /** + * Return the instance. + * + * @return \Access + */ + public static function instance() + { + static $result = null; + if (empty($result)) { + $result = new self(); + } + return $result; + } + + private function __construct() + { + + } + + public function can_edit() + { + return true; + } + + public function can_view() + { + return true; + } + + public function authorize() + { + return true; + } + +} + +/** + * Authorizev view access only + */ +class AccessForbidden extends Access +{ + + /** + * Return the instance. + * + * @return \AccessView + */ + public static function instance() + { + static $result = null; + if (empty($result)) { + $result = new self(); + } + return $result; + } + + private function __construct() + { + + } + + public function can_edit() + { + return false; + } + + public function can_view() + { + return false; + } + + public function authorize() + { + return false; + } + +} \ No newline at end of file diff --git a/main/inc/lib/controller.class.php b/main/inc/lib/controller.class.php new file mode 100644 index 0000000000..95817e210e --- /dev/null +++ b/main/inc/lib/controller.class.php @@ -0,0 +1,198 @@ + for the Univesity of Genevas + * @license see /license.txt + */ +class Controller +{ + + const PARAM_ACTION = 'action'; + + protected $access; + + protected function __construct($access = null) + { + $access = $access ? $access : Access::all(); + $this->access = $access; + } + + /** + * + * @return \Access + */ + public function access() + { + return $this->access; + } + + /** + * List of actions accepted by the controller. + * + * @return array + */ + public function get_actions() + { + $reflector = new ReflectionClass($this); + $constants = $reflector->getConstants(); + $result = array(); + foreach ($constants as $key => $value) { + if (strpos($key, 'ACTION') !== false) { + $result[$key] = $value; + } + } + return $result; + } + + /** + * Action to perform. + * Returns the request parameter. + * + * @return string + */ + public function get_action() + { + $result = Request::get(self::PARAM_ACTION); + $actions = $this->get_actions(); + $result = in_array($result, $actions) ? $result : ''; + return $result; + } + + /** + * Set up the environment. Set up breadcrumps, raise tracking event, etc. + */ + protected function prolog() + { + + } + + /** + * Whether the call is authorized or not. + * + * @return boolean + */ + public function authorize() + { + return $this->access()->authorize(); + } + + /** + * Returns a string containing dynamic javascript to be included in the template. + * This requires a {{javascript}} tag in a twigg template to appear. + * + * Note: + * + * A better approach to this method is to create a twigg "javascript" + * template and to include it where required. + * + * @return string + */ + public function javascript() + { + return ''; + } + +// public function check_token() +// { +// return (bool) Security::check_token('get'); +// } + + /** + * Run the controller. Dispatch action and execute requested tasks. + */ + public function run() + { + if (!$this->authorize()) { + $this->forbidden(); + return false; + } + + $this->prolog(); + $action = $this->get_action(); + if (empty($action)) { + $this->unknown(); + return; + } + $f = array($this, $action); + if (is_callable($f)) { + call_user_func($f); + } else { + $this->missing(); + } + } + + /** + * Unknown action. I.e. the action has not been registered. + * Possibly missing action declaration: + * + * const ACTION_XXX = 'XXX'; + * + * @return boolean + */ + public function unknown() + { + return false; + } + + /** + * + * @return boolean + */ + public function forbidden() + { + api_not_allowed(); + return false; + } + + /** + * Action exists but implementation is missing. + */ + public function missing() + { + echo 'No implementation'; + return false; + } + + /** + * Render a template using data. Adds a few common parameters to data. + * + * @see /main/template/default/course_description/ + * @param string $template + * @param array $data + */ + protected function render($template_name, $data) + { + $data = (object) $data; + $data->www = \Chamilo::url(); + $data->messages = isset($data->messages) ? $data->messages : array(); + $javascript = $this->javascript(); + if ($javascript) { + $data->javascript = $javascript; + } + + $tpl = new Template(); + foreach ($data as $key => $value) { + $tpl->assign($key, $value); + } + $template = $tpl->get_template($template_name); + $content = $tpl->fetch($template); + $tpl->assign('content', $content); + $tpl->display_one_col_template(); + } + + /** + * Render data as JSON + * + * @param any $data + */ + protected function render_json($data) + { + Header::content_type_json(); + echo json_encode($data); + } + +} \ No newline at end of file From 3d0383ffbd08a5e71435ada169c4c220579e2516 Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:15:13 +0200 Subject: [PATCH 4/9] minor: add a base controller for ajax calls --- main/inc/lib/ajax_controller.class.php | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 main/inc/lib/ajax_controller.class.php diff --git a/main/inc/lib/ajax_controller.class.php b/main/inc/lib/ajax_controller.class.php new file mode 100644 index 0000000000..57e58dedaa --- /dev/null +++ b/main/inc/lib/ajax_controller.class.php @@ -0,0 +1,57 @@ +run(); + * + * @author Laurent Opprecht for the Univesity of Genevas + * @license /license.txt + */ +class AjaxController extends \Controller +{ + + function forbidden() + { + $this->response(false, get_lang('YourAreNotAuthorized')); + } + + public function unknown() + { + $this->response(false, get_lang('UnknownAction')); + } + + /** + * Action exists but implementation is missing. + */ + public function missing() + { + $this->response(false, get_lang('NoImplementation')); + } + + /** + * Display a standard json responce. + * + * @param bool $success + * @param string $message + * @param object $data + */ + public function response($success = false, $message = '', $data = null) + { + $message = trim($message); + $response = (object) array(); + $response->success = $success; + if ($message) { + $response->message = Display::return_message($message, $success ? 'normal' : 'error'); + } else { + $response->message = ''; + } + $response->data = $data; + $this->render_json($response); + } + +} \ No newline at end of file From 646f7d12b19236948bd355259d5806eb3fadbc38 Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:16:16 +0200 Subject: [PATCH 5/9] see #5228: add standard ajax calls to glossary --- main/inc/ajax/glossary.ajax.php | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 main/inc/ajax/glossary.ajax.php diff --git a/main/inc/ajax/glossary.ajax.php b/main/inc/ajax/glossary.ajax.php new file mode 100644 index 0000000000..7f1c443ae2 --- /dev/null +++ b/main/inc/ajax/glossary.ajax.php @@ -0,0 +1,7 @@ +run(); \ No newline at end of file From 5905acf4ee3c8c18f2c20ee252804cb188906977 Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:16:35 +0200 Subject: [PATCH 6/9] minor: add sort up/sort down images --- main/img/sort_asc.png | Bin 0 -> 879 bytes main/img/sort_desc.png | Bin 0 -> 877 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 main/img/sort_asc.png create mode 100644 main/img/sort_desc.png diff --git a/main/img/sort_asc.png b/main/img/sort_asc.png new file mode 100644 index 0000000000000000000000000000000000000000..2531615c7afd5fb65bff013a9a1833c223dd20da GIT binary patch literal 879 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkEr-0p*)oROM_+H>et7bFK-9&fr{7*M`VzD7W>&nkuJyy! zY{eIIEHAK@C<3VmK%U!aKa=RUuk+@AvAdMDY>)aP$pu}ntWG7n9~DwEKd@!hk@t@` zM}{*TICZjE%7Q^B#9F&6;@mEG{?4B%>*MakRa%BxiKZ+!U;ZM}PW0yAHKnW_3f#Y! za)+4DITHHOV$;%7;u~K}h6Y;p9C`NYs9}Tnf2T8Re@3&{ciOQlDK*H?U^vzo`231l z0u$Q>2B}v*{}`GcOp0lbS^^AX2GtVRh?3-@)Wnih-4r0fU}RumscUGcYiJr`Xl`X- zWMyokYXD>zY*)L>|!YXH<>7-C>)Wn^MyWC+plceZ0SiiX_$l+3hB z+!}h0{X7oTkPdQ^PiAszUU4czMoCG5mA*dMuFSI32yq@#C>R*)8d`=J8d#YcS(ySoWd;m| z`i#Gz6fFsIV{m?2NqJ&XDnogBxn5>oc5!lIK`O{;v)|cB0Tl^D6qObwr!x3gRHmoq zDR?FWUH?X6-3y?!Izl==G{^_$Rghu%VAZ;rAk|>MzBgZW8mNWA)78&qol`;+0QV9< Ay#N3J literal 0 HcmV?d00001 diff --git a/main/img/sort_desc.png b/main/img/sort_desc.png new file mode 100644 index 0000000000000000000000000000000000000000..ba651e22b1702f9160b4227da7dd4a4071a45779 GIT binary patch literal 877 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkEZ5>xvzGhj#SrAwWrYnO(piAnUDnQRleBIGM3%YFUG5mv4} zCrymY&sCRya$B=iXYrXe%$811K}2N^0r7xu8jf;PvlxrI`8$qX(vvvdd;BuW%ke82SQoaExLc^KAXqE z)2p)My+dBxT>sAyvsTN^`mKez&R40`$qg5ZIc(V*;*v{cp0}wkp1W;zXzDxVe;MDC zG8p}~howwQefdHueI5>txo=IEOiYHbq!5J49%?! zjI4}JbPa$EgKf|IgkTy#Dy<;8fEo-9bPa$S3_}bot&B{pjDTE_hUhn5=TS7|=BH$) zRpQp5web@$DKMmioaB?4oSIjh%8*e~QedU854J0_EHyblH#a}8STDaQT|Wn+q*y49f?r*3AT|2K)8B`Kr@EEexKnelF{r5}E+A CTS2M- literal 0 HcmV?d00001 From ae232e80409a13d854b1f394a685c63336daaa4a Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:16:55 +0200 Subject: [PATCH 7/9] minor: object csv writer --- .../lib/system/io/csv_object_writer.class.php | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 main/inc/lib/system/io/csv_object_writer.class.php diff --git a/main/inc/lib/system/io/csv_object_writer.class.php b/main/inc/lib/system/io/csv_object_writer.class.php new file mode 100644 index 0000000000..4765ff486d --- /dev/null +++ b/main/inc/lib/system/io/csv_object_writer.class.php @@ -0,0 +1,129 @@ +property_name_1 = 'name 1'; + * $object->property_name_2 = 'name 2'; + * + * $map = array( 'property_name_1' => 'Header title 1', + * 'property_name_2' => 'Header title 2'); + * + * $writer = CsvObjectWriter::create($map, 'temp'); + * $writer->add($object); + * + * Output + * + * "Header title 1";"Header title 2" + * "name 1";"name 2" + * + * @license /licence.txt + * @author Laurent Opprecht + */ +class CsvObjectWriter extends CsvWriter +{ + + /** + * + * @param string|object $stream + * @return CsvWriter + */ + static function create($stream, $map = '*', $delimiter = ';', $enclosure = '"') + { + return new self($stream, $map = '*', $map, $delimiter, $enclosure); + } + + protected $map = '*'; + protected $headers_written = false; + + function __construct($stream, $map = '*', $delimiter = ';', $enclosure = '"') + { + parent::__construct($stream, $delimiter, $enclosure); + $this->map = $map; + } + + public function get_map() + { + return $this->map; + } + + /** + * + * @param object $item + * @return boolean + */ + public function put($item) + { + $data = $this->convert($item); + if (empty($data)) { + return false; + } + $this->writer_headers(); + parent::put($data); + return true; + } + + /** + * Convert object to array of data + * @param object $object + * @return array + */ + protected function convert($item) + { + $result = array(); + $map = $this->map; + if ($map == '*') { + return (array) $item; + } + foreach ($map as $key => $value) { + $result[$key] = isset($item->{$key}) ? $item->{$key} : ''; + } + return $result; + } + + /** + * + * @param array $items + */ + public function add_all($items) + { + foreach ($items as $item) { + $this->add($item); + } + } + + /** + * + * @param array|object $item + */ + public function add($item) + { + if (is_array($item)) { + $this->add_all($item); + return; + } + $this->put($item); + } + + protected function writer_headers() + { + if ($this->headers_written) { + return; + } + $this->headers_written = true; + + $map = $this->map; + if (!is_array($map)) { + return; + } + + $headers = array(); + foreach ($map as $key => $value) { + $headers[] = $value; + } + parent::put($headers); + } + +} \ No newline at end of file From c249fed2e88a2f0e2d193a87285b09ff4c280fcf Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:17:21 +0200 Subject: [PATCH 8/9] minor: add getter to csv writer --- main/inc/lib/system/io/csv_writer.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main/inc/lib/system/io/csv_writer.class.php b/main/inc/lib/system/io/csv_writer.class.php index 569807a245..b2737332d6 100644 --- a/main/inc/lib/system/io/csv_writer.class.php +++ b/main/inc/lib/system/io/csv_writer.class.php @@ -46,7 +46,11 @@ class CsvWriter { return $this->enclosure; } - + + function get_stream(){ + return $this->stream; + } + /** * * @return FileWriter From b0c934f7598321297491db525d9a73a63a6d760d Mon Sep 17 00:00:00 2001 From: Laurent Opprecht Date: Fri, 20 Jul 2012 17:17:52 +0200 Subject: [PATCH 9/9] minor: add a file store class to handle storing and loading of files to the disk --- main/inc/lib/file_store.class.php | 95 +++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 main/inc/lib/file_store.class.php diff --git a/main/inc/lib/file_store.class.php b/main/inc/lib/file_store.class.php new file mode 100644 index 0000000000..7b366530ba --- /dev/null +++ b/main/inc/lib/file_store.class.php @@ -0,0 +1,95 @@ + + */ +class FileStore +{ + + /** + * + * @param int $c_id + * @param string $sub_path + + * @return FileStore + */ + static function course($c_id, $sub_path = '') + { + + $sys_path = api_get_path(SYS_COURSE_PATH); + $course = api_get_course_info_by_id($c_id); + $course_path = $course['path']; + $path = $sys_path . $course_path . $sub_path; + if (!is_dir($path)) { + $mode = api_get_permissions_for_new_directories(); + $success = mkdir($path, $mode, true); + if (!$success) { + return false; + } + } + return new self($path); + } + + protected $root = ''; + + public function __construct($root) + { + $root = ltrim($root, '/'); + $root .= '/'; + $this->root = $root; + } + + public function root() + { + return $this->root; + } + + function accept($filename) + { + return (bool) filter_extension($filename); + } + + function add($path) + { + $root = $this->root(); + $id = $this->new_id(); + + $new_path = "$root/$id"; + $success = @move_uploaded_file($path, $new_path); + return $success ? $id : false; + } + + function remove($path){ + + $root = $this->root(); + $full_path = "$root/$path"; + if(is_file($full_path)){ + $result = unlink($full_path); + return $result; + } + return false; + } + + function get($id) + { + $root = $this->root(); + $result = "$root/$id"; + return $result; + } + + function new_id() + { + $root = $this->root(); + $id = uniqid(''); + $path = "$root/$id"; + while (file_exists($path)) { + $id = uniqid(''); + $path = "$root/$id"; + } + return $id; + } + +} \ No newline at end of file