public function testAddScheme() { $this->assertEquals('http://example.org', Html::addScheme('example.org')); $this->assertEquals('http://example.org', Html::addScheme('http://example.org')); $this->assertEquals('https://example.org', Html::addScheme('https://example.org')); $this->assertEquals('mailto:bob@bolt.cm', Html::addScheme('mailto:bob@bolt.cm')); }
/** * Get the excerpt of a given piece of text. * * @param int $length * @param bool $includeTitle * @param array|string|null $focus * * @return string|null */ public function getExcerpt($length = 200, $includeTitle = false, $focus = null) { $title = null; if ($includeTitle && $this->title !== null) { $title = Html::trimText(strip_tags($this->title), $length); $length = $length - strlen($title); } if ($this->body instanceof Content) { $this->body = $this->body->getValues(); } if (is_array($this->body)) { // Assume it's an array, strip some common fields that we don't need, implode the rest. $stripKeys = ['id', 'slug', 'datecreated', 'datechanged', 'username', 'ownerid', 'title', 'contenttype', 'status', 'taxonomy', 'templatefields']; foreach ($stripKeys as $key) { unset($this->body[$key]); } $excerpt = implode(' ', $this->body); } elseif (is_string($this->body) || is_object($this->body) && method_exists($this->body, '__toString')) { // otherwise we just use the string. $excerpt = (string) $this->body; } else { // Nope, got nothing. $excerpt = ''; } $excerpt = str_replace('>', '> ', $excerpt); if (empty($focus)) { $excerpt = Html::trimText(strip_tags($excerpt), $length); } else { $excerpt = $this->extractRelevant($focus, strip_tags($excerpt), $length); } if ($title !== null) { $excerpt = '<b>' . $title . '</b> ' . $excerpt; } return $excerpt; }
public function testBrandingData() { $app = $this->getApp(); $app['config']->set('general/branding/provided_by/0', 'testperson'); $app['config']->set('general/branding/provided_by/1', 'testemail'); $app['config']->set('general/branding/provided_link', Html::providerLink(['testperson', 'testemail'])); $request = Request::create('/', 'GET'); $response = $app->handle($request); $data = new BoltDataCollector($app); $data->collect($request, $response); $this->assertRegExp('/testperson/', $data->getBranding()); $this->assertRegExp('/testemail/', $data->getBranding()); }
public function testProviderLink() { $this->assertEquals('', Html::providerLink([])); $this->assertEquals('', Html::providerLink(false)); $this->assertEquals('', Html::providerLink("foo")); $this->assertEquals('<a href="mailto:supercool@example.org">Supercool Webdesign Co.</a>', Html::providerLink(['*****@*****.**', 'Supercool Webdesign Co.'])); $this->assertEquals('<a href="mailto:supercool@example.org">Supercool Webdesign Co.</a>', Html::providerLink(['mailto:supercool@example.org', 'Supercool Webdesign Co.'])); $this->assertEquals('<a href="http://example.org" target="_blank">Supercool Webdesign Co.</a>', Html::providerLink(['example.org', 'Supercool Webdesign Co.'])); $this->assertEquals('<a href="http://example.org" target="_blank">Supercool Webdesign Co.</a>', Html::providerLink(['http://example.org', 'Supercool Webdesign Co.'])); $this->assertEquals('<a href="https://www.example.org" target="_blank">Supercool Webdesign Co.</a>', Html::providerLink(['https://www.example.org', 'Supercool Webdesign Co.'])); $this->assertEquals('<a href="http://example.org" target="_blank">http://example.org</a>', Html::providerLink(['http://example.org'])); $this->assertEquals('<a href="http://example.org" target="_blank">no html, please!</a>', Html::providerLink(['http://example.org', '<blink>no html, please!</blink>'])); $this->assertEquals('<a href="http://example.org" target="_blank">http://example.org</a>', Html::providerLink(['http://example.org', '<b malformed HTML'])); }
/** * Creates RSS safe content. Wraps it in CDATA tags, strips style and * scripts out. Can optionally also return a (cleaned) excerpt. * * @param Content $record Bolt Content object * @param string $fields Comma separated list of fields to clean up * @param integer $excerptLength Number of chars of the excerpt * * @return string RSS safe string */ public function ampSafe($record, $fields = '', $excerptLength = 0) { // Make sure we have an array of fields. Even if it's only one. if (!is_array($fields)) { $fields = explode(',', $fields); } $fields = array_map('trim', $fields); $result = ''; foreach ($fields as $field) { if (!array_key_exists($field, $record->values)) { continue; } // Completely remove style and script blocks $maid = new Maid(['output-format' => 'html', 'allowed-tags' => ['a', 'b', 'br', 'hr', 'h1', 'h2', 'h3', 'h4', 'p', 'strong', 'em', 'i', 'u', 'strike', 'ul', 'ol', 'li', 'img'], 'allowed-attribs' => ['id', 'class', 'name', 'value', 'href', 'src']]); $result .= $maid->clean($record->values[$field]); } if ($excerptLength > 0) { $result = Html::trimText($result, $excerptLength); } return new \Twig_Markup('<![CDATA[ ' . $result . ' ]]>', 'utf-8'); }
public function description($record = null) { $this->initialize($record); if (!empty($this->values['record']['description'])) { $description = $this->values['record']['description']; } else { if (!empty($this->values['inferred']['description'])) { $description = $this->values['inferred']['description']; } else { $description = $this->values['default']['description']; } } return Html::trimText(strip_tags($description), $this->config['description_length']); }
/** * Create an excerpt for the content. * * @param integer $length * @param boolean $includetitle * * @return \Twig_Markup */ public function getExcerpt($length = 200, $includetitle = false) { if ($includetitle) { $title = Html::trimText(strip_tags($this->getTitle()), $length); $length = $length - strlen($title); } if ($length > 0) { $excerptParts = []; if (!empty($this->contenttype['fields'])) { foreach ($this->contenttype['fields'] as $key => $field) { // Skip empty fields, and fields used as 'title'. if (!isset($this->values[$key]) || in_array($key, $this->getTitleColumnName())) { continue; } // add 'text', 'html' and 'textarea' fields. if (in_array($field['type'], ['text', 'html', 'textarea'])) { $excerptParts[] = $this->values[$key]; } // add 'markdown' field if ($field['type'] === 'markdown') { $excerptParts[] = $this->app['markdown']->text($this->values[$key]); } } } $excerpt = implode(' ', $excerptParts); $excerpt = Html::trimText(strip_tags($excerpt), $length); } else { $excerpt = ''; } if (!empty($title)) { $excerpt = '<b>' . $title . '</b> ' . $excerpt; } return new \Twig_Markup($excerpt, 'UTF-8'); }
/** * Get a unique URL for a record * * @param string $title * @param integer $id * @param string $contenttypeslug * @param boolean $fulluri * @param boolean $allowempty * @param boolean $slugfield * * @return string */ public function getUri($title, $id = 0, $contenttypeslug = "", $fulluri = true, $allowempty = true, $slugfield = 'slug') { $contenttype = $this->getContentType($contenttypeslug); $tablename = $this->getContenttypeTablename($contenttype); $id = intval($id); $slug = $this->app['slugify']->slugify($title); // Don't allow strictly numeric slugs. if (is_numeric($slug)) { $slug = $contenttype['singular_slug'] . "-" . $slug; } // Only add '{contenttype}/' if $full is requested. if ($fulluri) { $prefix = '/' . $contenttype['singular_slug'] . '/'; } else { $prefix = ''; } $fields = $this->getContentTypeFields($contenttypeslug); //check if the fieldname exists, otherwise use 'slug' as fallback if (!in_array($slugfield, $fields)) { $slugfield = 'slug'; } $query = sprintf("SELECT id from %s WHERE %s=? and id!=?", $tablename, $slugfield); $res = $this->app['db']->executeQuery($query, array($slug, $id), array(\PDO::PARAM_STR, \PDO::PARAM_INT))->fetch(); if (!$res) { $uri = $prefix . $slug; } else { for ($i = 1; $i <= 10; $i++) { $newslug = Html::trimText($slug, 127 - strlen($i), false) . '-' . $i; $res = $this->app['db']->executeQuery($query, array($newslug, $id), array(\PDO::PARAM_STR, \PDO::PARAM_INT))->fetch(); if (!$res) { $uri = $prefix . $newslug; break; } } // otherwise, just get a random slug. if (empty($uri)) { $suffix = '-' . $this->app['randomgenerator']->generateString(6, 'abcdefghijklmnopqrstuvwxyz01234567890'); $slug = Html::trimText($slug, 128 - strlen($suffix), false) . $suffix; $uri = $prefix . $slug; } } // When storing, we should never have an empty slug/URI. If we can't make a nice one, set it to 'slug-XXXX'. if (!$allowempty && empty($uri)) { $uri = 'slug-' . $this->app['randomgenerator']->generateString(6, 'abcdefghijklmnopqrstuvwxyz01234567890'); } return $uri; }
/** * Create an excerpt for the given content. * * @param \Bolt\Legacy\Content|array|string $content * @param integer $length Defaults to 200 characters * * @return string Resulting excerpt */ public function excerpt($content, $length = 200) { // If it's an content object, let the object handle it. if (is_object($content)) { if (method_exists($content, 'excerpt')) { return $content->excerpt($length); } else { $output = $content; } } elseif (is_array($content)) { // Assume it's an array, strip some common fields that we don't need, implode the rest. $stripKeys = ['id', 'slug', 'datecreated', 'datechanged', 'username', 'ownerid', 'title', 'contenttype', 'status', 'taxonomy']; foreach ($stripKeys as $key) { unset($content[$key]); } $output = implode(' ', $content); } elseif (is_string($content)) { // otherwise we just use the string. $output = $content; } else { // Nope, got nothing. $output = ''; } $output = str_replace('>', '> ', $output); $output = Html::trimText(strip_tags($output), $length); return $output; }
public function keywords($record = null) { $this->initialize($record); if (!empty($this->values['record']['keywords'])) { $keywords = $this->values['record']['keywords']; } else { if (!empty($this->values['inferred']['keywords'])) { $keywords = $this->values['inferred']['keywords']; } else { $keywords = $this->values['default']['keywords']; } } $keywords = str_replace(array("\r", "\n"), "", $keywords); return Html::trimText(strip_tags($keywords), $this->config['keywords_length']); }
/** * Get an array of safe (sanitised) function arguments from a trace entry. * * @param array $args * * @return array */ protected function getSafeArguments(array $args) { $argsSafe = []; foreach ($args as $arg) { $type = gettype($arg); switch ($type) { case 'string': $argsSafe[] = sprintf('<span>"%s"</span>', Html::trimText($arg, 30)); break; case 'integer': case 'float': $argsSafe[] = sprintf('<span>%s</span>', $arg); break; case 'object': $className = get_class($arg); $shortName = (new \ReflectionClass($arg))->getShortName(); $argsSafe[] = sprintf('<abbr title="%s">%s</abbr>', $className, $shortName); break; case 'boolean': $argsSafe[] = $arg ? '[true]' : '[false]'; break; default: $argsSafe[] = '[' . $type . ']'; } } return $argsSafe; }
public function decorateTT($str) { return Html::decorateTT($str); }
/** * Read and parse the config.yml and config_local.yml configuration files. * * @return array */ protected function parseGeneral() { // Read the config and merge it. (note: We use temp variables to prevent // "Only variables should be passed by reference") $tempconfig = $this->parseConfigYaml('config.yml'); $tempconfiglocal = $this->parseConfigYaml('config_local.yml'); $general = Arr::mergeRecursiveDistinct($tempconfig, $tempconfiglocal); // Make sure old settings for 'contentsCss' are still picked up correctly if (isset($general['wysiwyg']['ck']['contentsCss'])) { $general['wysiwyg']['ck']['contentsCss'] = [1 => $general['wysiwyg']['ck']['contentsCss']]; } // Make sure old settings for 'accept_file_types' are not still picked up. Before 1.5.4 we used to store them // as a regex-like string, and we switched to an array. If we find the old style, fall back to the defaults. if (isset($general['accept_file_types']) && !is_array($general['accept_file_types'])) { unset($general['accept_file_types']); } // Merge the array with the defaults. Setting the required values that aren't already set. $general = Arr::mergeRecursiveDistinct($this->defaultConfig, $general); // Make sure the cookie_domain for the sessions is set properly. if (empty($general['cookies_domain'])) { $request = Request::createFromGlobals(); if ($request->server->get('HTTP_HOST', false)) { $hostSegments = explode(':', $request->server->get('HTTP_HOST')); $hostname = reset($hostSegments); } elseif ($request->server->get('SERVER_NAME', false)) { $hostname = $request->server->get('SERVER_NAME'); } else { $hostname = ''; } // Don't set the domain for a cookie on a "TLD" - like 'localhost', or if the server_name is an IP-address if (strpos($hostname, '.') > 0 && preg_match('/[a-z0-9]/i', $hostname)) { if (preg_match('/^www[0-9]*./', $hostname)) { $general['cookies_domain'] = '.' . preg_replace('/^www[0-9]*./', '', $hostname); } else { $general['cookies_domain'] = '.' . $hostname; } // Make sure we don't have consecutive '.'-s in the cookies_domain. $general['cookies_domain'] = str_replace('..', '.', $general['cookies_domain']); } else { $general['cookies_domain'] = ''; } } // Make sure Bolt's mount point is OK: $general['branding']['path'] = '/' . Str::makeSafe($general['branding']['path']); // Set the link in branding, if provided_by is set. $general['branding']['provided_link'] = Html::providerLink($general['branding']['provided_by']); $general['database'] = $this->parseDatabase($general['database']); return $general; }
/** * Create an HTML link to a given URL or contenttype/slug pair. * * @param string $location * @param string $label * * @return string */ public function link($location, $label = '[link]') { if ((string) $location === '') { return ''; } if (Html::isURL($location)) { $location = Html::addScheme($location); } elseif ($record = $this->app['storage']->getContent($location)) { $location = $record->link(); } return sprintf('<a href="%s">%s</a>', $location, $label); }
public function testDecorateTT() { $input = 'Lorem `ipsum` dolor.'; $this->assertEquals("Lorem <tt>ipsum</tt> dolor.", Html::decorateTT($input)); }