public function testHtmlentitiesDecode()
 {
     // setup
     $input = 'Ik heb géén bananen vandaag';
     $expectedResult = 'Ik heb géén bananen vandaag';
     // perform test
     $this->assertEquals(utf8_decode($expectedResult), SpoonFilter::htmlentitiesDecode(utf8_decode($input), 'iso-8859-1'));
     $this->assertEquals($expectedResult, SpoonFilter::htmlentitiesDecode($input, 'utf-8'));
 }
Example #2
0
 /**
  * Fetch data for this form from the database and reformat to csv rows.
  */
 private function setItems()
 {
     // init header labels
     $lblSessionId = SpoonFilter::ucfirst(BL::lbl('SessionId'));
     $lblSentOn = SpoonFilter::ucfirst(BL::lbl('SentOn'));
     $this->columnHeaders = array($lblSessionId, $lblSentOn);
     // fetch query and parameters
     list($query, $parameters) = $this->buildQuery();
     // get the data
     $records = (array) BackendModel::getDB()->getRecords($query, $parameters);
     $data = array();
     // reformat data
     foreach ($records as $row) {
         // first row of a submission
         if (!isset($data[$row['data_id']])) {
             $data[$row['data_id']][$lblSessionId] = $row['session_id'];
             $data[$row['data_id']][$lblSentOn] = SpoonDate::getDate('Y-m-d H:i:s', $row['sent_on'], BackendLanguage::getWorkingLanguage());
         }
         // value is serialized
         $value = unserialize($row['value']);
         // flatten arrays
         if (is_array($value)) {
             $value = implode(', ', $value);
         }
         // group submissions
         $data[$row['data_id']][$row['label']] = SpoonFilter::htmlentitiesDecode($value, null, ENT_QUOTES);
         // add into headers if not yet added
         if (!in_array($row['label'], $this->columnHeaders)) {
             $this->columnHeaders[] = $row['label'];
         }
     }
     // reorder data so they are in the correct column
     foreach ($data as $id => $row) {
         foreach ($this->columnHeaders as $header) {
             // submission has this field so add it
             if (isset($row[$header])) {
                 $this->rows[$id][] = $row[$header];
             } else {
                 $this->rows[$id][] = '';
             }
         }
     }
     // remove the keys
     $this->rows = array_values($this->rows);
 }
Example #3
0
 /**
  * Strips HTML from a string
  *
  * @return	string										A string with all HTML elements stripped.
  * @param string $string								The string with HTML in it.
  * @param mixed[optional] $exceptions					The HTML elements you want to exclude from stripping. Notation example: '<table><tr><td>'
  * @param bool[optional] $replaceAnchorsWithURL			If this is true it will replace all anchor elements with their href value.
  * @param bool[optional] $replaceImagesWithAltText		If this is true it will replace all img elements with their alt text.
  * @param bool[optional] $preserveParagraphLinebreaks	If this is true it will generate an additional EOL for paragraphs.
  * @param bool[optional] $stripTabs						If this is true it will strip all tabs from the string.
  */
 public static function stripHTML($string, $exceptions = null, $replaceAnchorsWithURL = false, $replaceImagesWithAltText = false, $preserveParagraphLinebreaks = false, $stripTabs = true)
 {
     // redefine
     $string = (string) $string;
     // check input
     if (is_array($exceptions)) {
         $exceptions = implode('', $exceptions);
     }
     // remove ugly and mac endlines
     $string = preg_replace('/\\r\\n/', PHP_EOL, $string);
     $string = preg_replace('/\\r/', PHP_EOL, $string);
     // remove tabs
     if ($stripTabs) {
         $string = preg_replace("/\t/", '', $string);
     }
     // remove the style- and head-tags and all their contents
     $string = preg_replace('|\\<style.*\\>(.*\\n*)\\</style\\>|is', '', $string);
     $string = preg_replace('|\\<head.*\\>(.*\\n*)\\</head\\>|is', '', $string);
     // replace images with their alternative content
     // eg. <img src="path/to/the/image.jpg" alt="My image" /> => My image
     if ($replaceImagesWithAltText) {
         $string = preg_replace('|\\<img[^>]*alt="(.*)".*/\\>|isU', '$1', $string);
     }
     // replace links with the inner html of the link with the url between ()
     // eg.: <a href="http://site.domain.com">My site</a> => My site (http://site.domain.com)
     if ($replaceAnchorsWithURL) {
         $string = preg_replace('|<a.*href="(.*)".*>(.*)</a>|isU', '$2 ($1)', $string);
     }
     // check if we need to preserve paragraphs and/or breaks
     $exceptions = $preserveParagraphLinebreaks ? $exceptions . '<p>' : $exceptions;
     // strip HTML tags and preserve paragraphs
     $string = strip_tags($string, $exceptions);
     // remove multiple with a single one
     $string = preg_replace('/\\n\\s/', PHP_EOL, $string);
     $string = preg_replace('/\\n{2,}/', PHP_EOL, $string);
     // for each linebreak, table row or- paragraph end we want an additional linebreak at the end
     if ($preserveParagraphLinebreaks) {
         $string = preg_replace('|<p>|', '', $string);
         $string = preg_replace('|</p>|', PHP_EOL, $string);
     }
     // trim whitespace and strip HTML tags
     $string = trim($string);
     // replace html entities that aren't replaced by SpoonFilter::htmlentitiesDecode (should be solved when using a newer Spoon Library)
     $string = str_replace('&euro;', 'EUR', $string);
     $string = str_replace('&#8364;', 'EUR', $string);
     $string = str_replace('&#8211;', '-', $string);
     $string = str_replace('&#8230;', '...', $string);
     // decode html entities
     $string = SpoonFilter::htmlentitiesDecode($string);
     // return the plain text
     return $string;
 }
Example #4
0
 /**
  * Truncate a string
  *    syntax: {$var|truncate:max-length[:append-hellip][:closest-word]}
  *
  * @param string $var         The string passed from the template.
  * @param int    $length      The maximum length of the truncated string.
  * @param bool   $useHellip   Should a hellip be appended if the length exceeds the requested length?
  * @param bool   $closestWord Truncate on exact length or on closest word?
  * @return string
  */
 public static function truncate($var = null, $length, $useHellip = true, $closestWord = false)
 {
     // init vars
     $charset = BackendModel::getContainer()->getParameter('kernel.charset');
     // remove special chars, all of them, also the ones that shouldn't be there.
     $var = \SpoonFilter::htmlentitiesDecode($var, null, ENT_QUOTES);
     // remove HTML
     $var = strip_tags($var);
     // less characters
     if (mb_strlen($var) <= $length) {
         return \SpoonFilter::htmlspecialchars($var);
     } else {
         // more characters
         // hellip is seen as 1 char, so remove it from length
         if ($useHellip) {
             $length = $length - 1;
         }
         // truncate
         if ($closestWord) {
             $var = mb_substr($var, 0, strrpos(substr($var, 0, $length + 1), ' '), $charset);
         } else {
             $var = mb_substr($var, 0, $length, $charset);
         }
         // add hellip
         if ($useHellip) {
             $var .= '…';
         }
         // return
         return \SpoonFilter::htmlspecialchars($var, ENT_QUOTES);
     }
 }
 /**
  * Process the XML and treat it as a blogpost
  *
  * @param SimpleXMLElement $xml The XML to process.
  * @return bool
  */
 private function processXMLAsPost(SimpleXMLElement $xml)
 {
     // init var
     $postID = substr((string) $xml->id, mb_strpos((string) $xml->id, 'post-') + 5);
     // validate
     if ($postID == '') {
         return false;
     }
     if ((string) $xml->title == '') {
         return false;
     }
     // build item
     $item['id'] = (int) BackendBlogModel::getMaximumId() + 1;
     $item['user_id'] = BackendAuthentication::getUser()->getUserId();
     $item['hidden'] = 'N';
     $item['allow_comments'] = 'Y';
     $item['num_comments'] = 0;
     $item['status'] = 'active';
     $item['language'] = BL::getWorkingLanguage();
     $item['publish_on'] = BackendModel::getUTCDate(null, strtotime((string) $xml->published));
     $item['created_on'] = BackendModel::getUTCDate(null, strtotime((string) $xml->published));
     $item['edited_on'] = BackendModel::getUTCDate(null, strtotime((string) $xml->updated));
     $item['category_id'] = 1;
     $item['title'] = (string) $xml->title;
     $item['text'] = (string) $xml->content;
     // set drafts hidden
     if (strtotime((string) $xml->published) > time()) {
         $item['hidden'] = 'Y';
         $item['status'] = 'draft';
     }
     // build meta
     $meta = array();
     $meta['keywords'] = $item['title'];
     $meta['keywords_overwrite'] = 'N';
     $meta['description'] = $item['title'];
     $meta['description_overwrite'] = 'N';
     $meta['title'] = $item['title'];
     $meta['title_overwrite'] = 'N';
     $meta['url'] = BackendBlogModel::getURL($item['title']);
     $meta['url_overwrite'] = 'N';
     // replace f****d up links
     $item['text'] = preg_replace('|<a(.*)onblur="(.*)"(.*)>|Ui', '<a$1$3>', $item['text']);
     // fix images
     $item['text'] = preg_replace('|<img(.*)border="(.*)"(.*)>|Ui', '<img$1$3>', $item['text']);
     // remove inline styles
     $item['text'] = preg_replace('|<(.*)style="(.*)"(.*)>|Ui', '<$1$3>', $item['text']);
     // whitespace
     $item['text'] = preg_replace('|\\s{2,}|', ' ', $item['text']);
     // cleanup
     $search = array('<br /><br />', '<div><br /></div>', '<div>', '</div>', '<i>', '</i>', '<b>', '</b>', '<p><object', '</object></p>', '<p><p>', '</p></p>', '...');
     $replace = array('</p><p>', '</p><p>', '', '', '<em>', '</em>', '<strong>', '</strong>', '<object', '</object>', '<p>', '</p>', '…');
     // cleanup
     $item['text'] = '<p>' . str_replace($search, $replace, SpoonFilter::htmlentitiesDecode($item['text'])) . '</p>';
     // get images
     $matches = array();
     preg_match_all('/<img.*src="(.*)".*\\/>/Ui', $item['text'], $matches);
     // any images?
     if (isset($matches[1]) && !empty($matches[1])) {
         // init var
         $imagesPath = FRONTEND_FILES_PATH . '/userfiles/images/blog';
         $imagesURL = FRONTEND_FILES_URL . '/userfiles/images/blog';
         // create dir if needed
         if (!SpoonDirectory::exists($imagesPath)) {
             SpoonDirectory::create($imagesPath);
         }
         // loop matches
         foreach ($matches[1] as $key => $file) {
             // get file info
             $fileInfo = SpoonFile::getInfo($file);
             // init var
             $destinationFile = $item['id'] . '_' . $fileInfo['basename'];
             try {
                 // download
                 SpoonFile::download($file, $imagesPath . '/' . $destinationFile);
                 // replace the old URL with the new one
                 $item['text'] = str_replace($file, $imagesURL . '/' . $destinationFile, $item['text']);
             } catch (Exception $e) {
                 // ignore
             }
         }
     }
     // get links
     $matches = array();
     preg_match_all('/<a.*href="(.*)".*\\/>/Ui', $item['text'], $matches);
     // any images?
     if (isset($matches[1]) && !empty($matches[1])) {
         // loop matches
         foreach ($matches[1] as $key => $file) {
             // get new link
             $replaceWith = self::download($file, $item['id']);
             // should we replace?
             if ($replaceWith !== false) {
                 // replace the old URL with the new one
                 $item['text'] = str_replace($file, $replaceWith, $item['text']);
             }
         }
     }
     // insert meta
     $item['meta_id'] = BackendModel::getDB(true)->insert('meta', $meta);
     // insert
     BackendBlogModel::insert($item);
     // store the post
     $this->newIds[$postID] = $item['id'];
     // get tags
     $tags = array();
     // loop categories
     foreach ($xml->category as $category) {
         // is this a tag? if so add it
         if ((string) $category['scheme'] == 'http://www.blogger.com/atom/ns#') {
             $tags[] = (string) $category['term'];
         }
     }
     // any tags?
     if (!empty($tags)) {
         BackendTagsModel::saveTags($item['id'], implode(',', $tags), $this->getModule());
     }
     // return
     return true;
 }
Example #6
0
 /**
  * Generate an url, using the predefined callback.
  *
  * @param string $URL The base-url to start from.
  * @return string
  * @throws Exception When the function does not exist
  */
 public function generateURL($URL)
 {
     // validate (check if the function exists)
     if (!is_callable(array($this->callback['class'], $this->callback['method']))) {
         throw new Exception('The callback-method doesn\'t exist.');
     }
     // when using ->getValue() in SpoonFormText fields the function is using htmlentities(),
     // so we must decode it again first!
     $URL = \SpoonFilter::htmlentitiesDecode($URL);
     // build parameters for use in the callback
     $parameters[] = CommonUri::getUrl($URL);
     // add parameters set by user
     if (!empty($this->callback['parameters'])) {
         foreach ($this->callback['parameters'] as $parameter) {
             $parameters[] = $parameter;
         }
     }
     // get the real url
     return call_user_func_array(array($this->callback['class'], $this->callback['method']), $parameters);
 }
Example #7
0
 /**
  * Adds an email to the queue.
  *
  * @param string $subject The subject for the email.
  * @param string $template The template to use.
  * @param array[optional] $variables Variables that should be assigned in the email.
  * @param string[optional] $toEmail The to-address for the email.
  * @param string[optional] $toName The to-name for the email.
  * @param string[optional] $fromEmail The from-address for the mail.
  * @param string[optional] $fromName The from-name for the mail.
  * @param string[optional] $replyToEmail The replyto-address for the mail.
  * @param string[optional] $replyToName The replyto-name for the mail.
  * @param bool[optional] $queue Should the mail be queued?
  * @param int[optional] $sendOn When should the email be send, only used when $queue is true.
  * @param bool[optional] $isRawHTML If this is true $template will be handled as raw HTML, so no parsing of $variables is done.
  * @param string[optional] $plainText The plain text version.
  * @param array[optional] $attachments Paths to attachments to include.
  * @return int The id of the inserted mail.
  */
 public static function addEmail($subject, $template, array $variables = null, $toEmail = null, $toName = null, $fromEmail = null, $fromName = null, $replyToEmail = null, $replyToName = null, $queue = false, $sendOn = null, $isRawHTML = false, $plainText = null, array $attachments = null)
 {
     $subject = (string) strip_tags($subject);
     $template = (string) $template;
     // set defaults
     $to = BackendModel::getModuleSetting('core', 'mailer_to');
     $from = BackendModel::getModuleSetting('core', 'mailer_from');
     $replyTo = BackendModel::getModuleSetting('core', 'mailer_reply_to');
     // set recipient/sender headers
     $email['to_email'] = $toEmail === null ? (string) $to['email'] : $toEmail;
     $email['to_name'] = $toName === null ? (string) $to['name'] : $toName;
     $email['from_email'] = $fromEmail === null ? (string) $from['email'] : $fromEmail;
     $email['from_name'] = $fromName === null ? (string) $from['name'] : $fromName;
     $email['reply_to_email'] = $replyToEmail === null ? (string) $replyTo['email'] : $replyToEmail;
     $email['reply_to_name'] = $replyToName === null ? (string) $replyTo['name'] : $replyToName;
     // validate
     if (!SpoonFilter::isEmail($email['to_email'])) {
         throw new BackendException('Invalid e-mail address for recipient.');
     }
     if (!SpoonFilter::isEmail($email['from_email'])) {
         throw new BackendException('Invalid e-mail address for sender.');
     }
     if (!SpoonFilter::isEmail($email['reply_to_email'])) {
         throw new BackendException('Invalid e-mail address for reply-to address.');
     }
     // build array
     $email['subject'] = SpoonFilter::htmlentitiesDecode($subject);
     if ($isRawHTML) {
         $email['html'] = $template;
     } else {
         $email['html'] = self::getTemplateContent($template, $variables);
     }
     if ($plainText !== null) {
         $email['plain_text'] = $plainText;
     }
     $email['created_on'] = BackendModel::getUTCDate();
     // init var
     $matches = array();
     // get internal links
     preg_match_all('|href="/(.*)"|i', $email['html'], $matches);
     // any links?
     if (!empty($matches[0])) {
         // init vars
         $search = array();
         $replace = array();
         // loop the links
         foreach ($matches[0] as $key => $link) {
             $search[] = $link;
             $replace[] = 'href="' . SITE_URL . '/' . $matches[1][$key] . '"';
         }
         // replace
         $email['html'] = str_replace($search, $replace, $email['html']);
     }
     // init var
     $matches = array();
     // get internal urls
     preg_match_all('|src="/(.*)"|i', $email['html'], $matches);
     // any links?
     if (!empty($matches[0])) {
         // init vars
         $search = array();
         $replace = array();
         // loop the links
         foreach ($matches[0] as $key => $link) {
             $search[] = $link;
             $replace[] = 'src="' . SITE_URL . '/' . $matches[1][$key] . '"';
         }
         // replace
         $email['html'] = str_replace($search, $replace, $email['html']);
     }
     // attachments added
     if (!empty($attachments)) {
         // add attachments one by one
         foreach ($attachments as $attachment) {
             // only add existing files
             if (SpoonFile::exists($attachment)) {
                 $email['attachments'][] = $attachment;
             }
         }
         // serialize :)
         if (!empty($email['attachments'])) {
             $email['attachments'] = serialize($email['attachments']);
         }
     }
     // set send date
     if ($queue) {
         if ($sendOn === null) {
             $email['send_on'] = BackendModel::getUTCDate('Y-m-d H') . ':00:00';
         } else {
             $email['send_on'] = BackendModel::getUTCDate('Y-m-d H:i:s', (int) $sendOn);
         }
     }
     // insert the email into the database
     $id = BackendModel::getDB(true)->insert('emails', $email);
     // trigger event
     BackendModel::triggerEvent('core', 'after_email_queued', array('id' => $id));
     // if queue was not enabled, send this mail right away
     if (!$queue) {
         self::send($id);
     }
     // return
     return $id;
 }
Example #8
0
 /**
  * Truncate a string
  *    syntax: {{ $string|truncate($max-length, $append-hellip, $closest-word) }}.
  *
  * @param string $string      The string passed from the template.
  * @param int    $length      The maximum length of the truncated string.
  * @param bool   $useHellip   Should a hellip be appended if the length exceeds the requested length?
  * @param bool   $closestWord Truncate on exact length or on closest word?
  *
  * @return string
  */
 public static function truncate($string, $length, $useHellip = true, $closestWord = false)
 {
     // remove special chars, all of them, also the ones that shouldn't be there.
     $string = \SpoonFilter::htmlentitiesDecode($string, null, ENT_QUOTES);
     // remove HTML
     $string = strip_tags($string);
     // less characters
     if (mb_strlen($string) <= $length) {
         return \SpoonFilter::htmlspecialchars($string);
     } else {
         // more characters
         // hellip is seen as 1 char, so remove it from length
         if ($useHellip) {
             --$length;
         }
         // truncate
         if ($closestWord) {
             $string = mb_substr($string, 0, strrpos(substr($string, 0, $length + 1), ' '), 'UTF-8');
         } else {
             $string = mb_substr($string, 0, $length, 'UTF8');
         }
         // add hellip
         if ($useHellip) {
             $string .= '…';
         }
         // return
         return \SpoonFilter::htmlspecialchars($string, ENT_QUOTES);
     }
 }