9da1f0b19a383e3b82bc8de4e9384ba70ece4306
[moodle.git] / lib / classes / message / inbound / handler.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  * Abstract class describing Inbound Message Handlers.
19  *
20  * @package    core_message
21  * @copyright  2014 Andrew Nicols
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
24 namespace core\message\inbound;
26 /**
27  * Abstract class describing Inbound Message Handlers.
28  *
29  * @copyright  2014 Andrew NIcols
30  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31  *
32  * @property-read int $id The ID of the handler in the database
33  * @property-read string $component The component of this handler
34  * @property-read int $defaultexpiration Default expiration of new addresses for this handler
35  * @property-read string $description The description of this handler
36  * @property-read string $name The name of this handler
37  * @property-read bool $validateaddress Whether the address validation is a requiredment
38  * @property-read bool $enabled Whether this handler is currently enabled
39  * @property-read string $classname The name of handler class
40  */
41 abstract class handler {
43     /**
44      * @var int $id The id of the handler in the database.
45      */
46     private $id = null;
48     /**
49      * @var string $component The component to which this handler belongs.
50      */
51     private $component = '';
53     /**
54      * @var int $defaultexpiration The default expiration time to use when created a new key.
55      */
56     private $defaultexpiration = WEEKSECS;
58     /**
59      * @var bool $validateaddress Whether to validate the sender address when processing this handler.
60      */
61     private $validateaddress = true;
63     /**
64      * @var bool $enabled Whether this handler is currently enabled.
65      */
66     private $enabled = false;
68     /**
69      * @var $accessibleproperties A list of the properties which can be read.
70      */
71     private $accessibleproperties = array(
72         'id' => true,
73         'component' => true,
74         'defaultexpiration' => true,
75         'validateaddress' => true,
76         'enabled' => true,
77     );
79     /**
80      * Magic getter to fetch the specified key.
81      *
82      * @param string $key The name of the key to retrieve
83      */
84     public function __get($key) {
85         // Some properties have logic behind them.
86         $getter = 'get_' . $key;
87         if (method_exists($this, $getter)) {
88             return $this->$getter();
89         }
91         // Check for a commonly accessibly property.
92         if (isset($this->accessibleproperties[$key])) {
93             return $this->$key;
94         }
96         // Unknown property - bail.
97         throw new \coding_exception('unknown_property ' . $key);
98     }
100     /**
101      * Set the id name.
102      *
103      * @param int $id The id to set
104      * @return int The newly set id
105      */
106     public function set_id($id) {
107         return $this->id = $id;
108     }
110     /**
111      * Set the component name.
112      *
113      * @param string $component The component to set
114      * @return string The newly set component
115      */
116     public function set_component($component) {
117         return $this->component = $component;
118     }
120     /**
121      * Whether the current handler allows changes to the address validation
122      * setting.
123      *
124      * By default this will return true, but for some handlers it may be
125      * necessary to disallow such changes.
126      *
127      * @return boolean
128      */
129     public function can_change_validateaddress() {
130         return true;
131     }
133     /**
134      * Set whether validation of the address is required.
135      *
136      * @param bool $validateaddress The new state of validateaddress
137      * @return bool
138      */
139     public function set_validateaddress($validateaddress) {
140         return $this->validateaddress = $validateaddress;
141     }
143     /**
144      * Whether the current handler allows changes to expiry of the generated email address.
145      *
146      * By default this will return true, but for some handlers it may be
147      * necessary to disallow such changes.
148      *
149      * @return boolean
150      */
151     public function can_change_defaultexpiration() {
152         return true;
153     }
155     /**
156      * Whether this handler can be disabled (or enabled).
157      *
158      * By default this will return true, but for some handlers it may be
159      * necessary to disallow such changes. For example, a core handler to
160      * handle rejected mail validation should not be disabled.
161      *
162      * @return boolean
163      */
164     public function can_change_enabled() {
165         return true;
166     }
168     /**
169      * Set the enabled name.
170      *
171      * @param bool $enabled The new state of enabled
172      * @return bool
173      */
174     public function set_enabled($enabled) {
175         return $this->enabled = $enabled;
176     }
178     /**
179      * Set the default validity for new keys.
180      *
181      * @param int $period The time in seconds before a key expires
182      * @return int
183      */
184     public function set_defaultexpiration($period) {
185         return $this->defaultexpiration = $period;
186     }
188     /**
189      * Get the non-namespaced name of the current class.
190      *
191      * @return string The classname
192      */
193     private function get_classname() {
194         $classname = get_class($this);
195         if (strpos($classname, '\\') !== 0) {
196             $classname = '\\' . $classname;
197         }
199         return $classname;
200     }
202     /**
203      * Return a description for the current handler.
204      *
205      * @return string
206      */
207     protected abstract function get_description();
209     /**
210      * Return a name for the current handler.
211      * This appears in the admin pages as a human-readable name.
212      *
213      * @return string
214      */
215     protected abstract function get_name();
217     /**
218      * Process the message against the current handler.
219      *
220      * @param \stdClass $record The Inbound Message Handler record
221      * @param \stdClass $messagedata The message data
222      */
223     public abstract function process_message(\stdClass $record, \stdClass $messagedata);
225     /**
226      * Return the content of any success notification to be sent.
227      * Both an HTML and Plain Text variant must be provided.
228      *
229      * If this handler does not need to send a success notification, then
230      * it should return a falsey value.
231      *
232      * @param \stdClass $messagedata The message data.
233      * @param \stdClass $handlerresult The record for the newly created post.
234      * @return \stdClass with keys `html` and `plain`.
235      */
236     public function get_success_message(\stdClass $messagedata, $handlerresult) {
237         return false;
238     }
240     /**
241      * Remove quoted message string from the text (NOT HTML) message.
242      *
243      * @param \stdClass $messagedata The Inbound Message record
244      *
245      * @return array message and message format to use.
246      */
247     protected static function remove_quoted_text($messagedata) {
248         if (!empty($messagedata->plain)) {
249             $text = $messagedata->plain;
250         } else {
251             $text = html_to_text($messagedata->html);
252         }
253         $messageformat = FORMAT_PLAIN;
255         $splitted = preg_split("/\n|\r/", $text);
256         if (empty($splitted)) {
257             return array($text, $messageformat);
258         }
260         $i = 0;
261         $flag = false;
262         foreach ($splitted as $i => $element) {
263             if (stripos($element, ">") === 0) {
264                 // Quoted text found.
265                 $flag = true;
266                 // Remove 2 non empty line before this.
267                 for ($j = $i - 1; ($j >= 0); $j--) {
268                     $element = $splitted[$j];
269                     if (!empty($element)) {
270                         unset($splitted[$j]);
271                         break;
272                     }
273                 }
274                 break;
275             }
276         }
277         if ($flag) {
278             // Quoted text was found.
279             // Retrieve everything from the start until the line before the quoted text.
280             $splitted = array_slice($splitted, 0, $i-1);
282             // Strip out empty lines towards the end, since a lot of clients add a huge chunk of empty lines.
283             $reverse = array_reverse($splitted);
284             foreach ($reverse as $i => $line) {
285                 if (empty($line)) {
286                     unset($reverse[$i]);
287                 } else {
288                     // Non empty line found.
289                     break;
290                 }
291             }
293             $replaced = implode(PHP_EOL, array_reverse($reverse));
294             $message = trim($replaced);
295         } else {
296             // No quoted text, fallback to original text.
297             if (!empty($messagedata->html)) {
298                 $message = $messagedata->html;
299                 $messageformat = FORMAT_HTML;
300             } else {
301                 $message = $messagedata->plain;
302             }
303         }
304         return array($message, $messageformat);
305     }