Merge branch 'MDL-70066-master' of git://github.com/lameze/moodle
[moodle.git] / badges / classes / external / badgeclass_exporter.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Contains class for displaying a badgeclass.
19  *
20  * @package   core_badges
21  * @copyright 2019 Damyon Wiese
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 namespace core_badges\external;
27 defined('MOODLE_INTERNAL') || die();
29 use core\external\exporter;
30 use renderer_base;
32 /**
33  * Class for displaying a badge competency.
34  *
35  * @package   core_badges
36  * @copyright 2019 Damyon Wiese
37  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class badgeclass_exporter extends exporter {
41     /**
42      * Constructor - saves the persistent object, and the related objects.
43      *
44      * @param mixed $data - Either an stdClass or an array of values.
45      * @param array $related - An optional list of pre-loaded objects related to this object.
46      */
47     public function __construct($data, $related = array()) {
48         $pick = $this->pick_related();
49         foreach ($pick as $one) {
50             $isarray = false;
51             // Allow [] to mean an array of values.
52             if (substr($one, -2) === '[]') {
53                 $one = substr($one, 0, -2);
54                 $isarray = true;
55             }
56             $prefixed = 'related_' . $one;
57             if (property_exists($data, $one) && !array_key_exists($one, $related)) {
58                 if ($isarray) {
59                     $newrelated = [];
60                     foreach ($data->$one as $item) {
61                         $newrelated[] = (object) $item;
62                     }
63                     $related[$one] = $newrelated;
64                 } else {
65                     $related[$one] = (object) $data->$one;
66                 }
67                 unset($data->$one);
68             } else if (property_exists($data, $prefixed) && !array_key_exists($one, $related)) {
69                 if ($isarray) {
70                     $newrelated = [];
71                     foreach ($data->$prefixed as $item) {
72                         $newrelated[] = (object) $item;
73                     }
74                     $related[$one] = $newrelated;
75                 } else {
76                     $related[$one] = (object) $data->$prefixed;
77                 }
78                 unset($data->$prefixed);
79             } else if (!array_key_exists($one, $related)) {
80                 $related[$one] = null;
81             }
82         }
83         parent::__construct($data, $related);
84     }
86     /**
87      * List properties passed in $data that should be moved to $related in the constructor.
88      *
89      * @return array A list of properties to move from $data to $related.
90      */
91     public static function pick_related() {
92         return ['alignment[]', 'criteria'];
93     }
95     /**
96      * Map data from a request response to the internal structure.
97      *
98      * @param stdClass $data The remote data.
99      * @param string $apiversion The backpack version used to communicate remotely.
100      * @return stdClass
101      */
102     public static function map_external_data($data, $apiversion) {
103         $mapped = new \stdClass();
104         if (isset($data->entityType)) {
105             $mapped->type = $data->entityType;
106         } else {
107             $mapped->type = $data->type;
108         }
109         if (isset($data->entityId)) {
110             $mapped->id = $data->entityId;
111         } else {
112             $mapped->id = $data->id;
113         }
114         $mapped->name = $data->name;
115         $mapped->image = $data->image;
116         $mapped->issuer = $data->issuer;
117         $mapped->description = $data->description;
118         if (isset($data->openBadgeId)) {
119             $mapped->hostedUrl = $data->openBadgeId;
120         } else {
121             $mapped->hostedUrl = $data->id;
122         }
124         return $mapped;
125     }
127     /**
128      * Return the list of properties.
129      *
130      * @return array
131      */
132     protected static function define_properties() {
133         return [
134             'type' => [
135                 'type' => PARAM_ALPHA,
136                 'description' => 'BadgeClass',
137             ],
138             'id' => [
139                 'type' => PARAM_RAW,
140                 'description' => 'Unique identifier for this badgeclass',
141             ],
142             'issuer' => [
143                 'type' => PARAM_RAW,
144                 'description' => 'Unique identifier for this badgeclass',
145                 'optional' => true,
146             ],
147             'name' => [
148                 'type' => PARAM_TEXT,
149                 'description' => 'Name of the badgeclass',
150             ],
151             'image' => [
152                 'type' => PARAM_URL,
153                 'description' => 'URL to the image.',
154             ],
155             'description' => [
156                 'type' => PARAM_TEXT,
157                 'description' => 'Description of the badge class.',
158             ],
159             'hostedUrl' => [
160                 'type' => PARAM_RAW,
161                 'description' => 'Identifier of the open badge for this assertion',
162                 'optional' => true,
163             ],
164         ];
165     }
167     /**
168      * Returns a list of objects that are related.
169      *
170      * @return array
171      */
172     protected static function define_related() {
173         return array(
174             'context' => 'context',
175             'alignment' => 'stdClass[]?',
176             'criteria' => 'stdClass?',
177         );
178     }
180     /**
181      * Return the list of additional properties.
182      *
183      * @return array
184      */
185     protected static function define_other_properties() {
186         return array(
187             'alignment' => array(
188                 'type' => alignment_exporter::read_properties_definition(),
189                 'optional' => true,
190                 'multiple' => true
191             ),
192             'criteriaUrl' => array(
193                 'type' => PARAM_URL,
194                 'optional' => true
195             ),
196             'criteriaNarrative' => array(
197                 'type' => PARAM_TEXT,
198                 'optional' => true
199             )
200         );
201     }
203     /**
204      * We map from related data passed as data to this exporter to clean exportable values.
205      *
206      * @param renderer_base $output
207      * @return array
208      */
209     protected function get_other_values(renderer_base $output) {
210         global $DB;
211         $result = [];
213         if (array_key_exists('alignment', $this->related) && $this->related['alignment'] !== null) {
214             $alignment = [];
215             foreach ($this->related['alignment'] as $alignment) {
216                 $exporter = new alignment_exporter($alignment, $this->related);
217                 $alignments[] = $exporter->export($output);
218             }
219             $result['alignment'] = $alignments;
220         }
221         if (array_key_exists('criteria', $this->related) && $this->related['criteria'] !== null) {
222             if (property_exists($this->related['criteria'], 'id') && $this->related['criteria']->id !== null) {
223                 $result['criteriaUrl'] = $this->related['criteria']->id;
224             }
225             if (property_exists($this->related['criteria'], 'narrative') && $this->related['criteria']->narrative !== null) {
226                 $result['criteriaNarrative'] = $this->related['criteria']->narrative;
227             }
228         }
230         return $result;
231     }