Warning: touch(): Unable to create file /home/www/vvveb/demo/public/page-cache/demo.vvveb.com/ru/product/product-three.new because Permission denied in /home/www/vvveb/demo/system/page-cache.php on line 284
Exception:
Array
(
    [message] => Call to undefined function Vvveb\Plugins\Seo\Modules\Breadcrumbs\mb_substr()
    [file] => /home/www/vvveb/demo/plugins/seo/modules/breadcrumbs/breadcrumbs.php
    [line_no] => 37
    [line] => 			$item = ['@type' => 'ListItem', 'position' => $pos++, 'name' => mb_substr(strip_tags((string)($crumb['name'] ?? '')), 0, 200)];	 // <==

    [lines] => Array
        (
            [0] => 	}

            [1] => 

            [2] => 	/** Build ordered crumbs: each [name, url|null]. */

            [3] => 	public static function crumbs(array $trail): array {

            [4] => 		$out = [];

            [5] => 		$pos = 1;

            [6] => 		foreach ($trail as $crumb) {

            [7] => 			$item = ['@type' => 'ListItem', 'position' => $pos++, 'name' => mb_substr(strip_tags((string)($crumb['name'] ?? '')), 0, 200)];	 // <==

            [8] => 			if (! empty($crumb['url'])) {

            [9] => 				$item['item'] = $crumb['url'];

            [10] => 			}

            [11] => 			$out[] = $item;

            [12] => 		}

            [13] => 

        )

    [trace] => #0 /home/www/vvveb/demo/plugins/seo/modules/breadcrumbs/breadcrumbs.php(49): Vvveb\Plugins\Seo\Modules\Breadcrumbs\Breadcrumbs::crumbs()
#1 /home/www/vvveb/demo/plugins/seo/modules/breadcrumbs/breadcrumbs.php(61): Vvveb\Plugins\Seo\Modules\Breadcrumbs\Breadcrumbs::jsonLd()
#2 /home/www/vvveb/demo/plugins/seo/modules/breadcrumbs/breadcrumbs.php(70): Vvveb\Plugins\Seo\Modules\Breadcrumbs\Breadcrumbs->emit()
#3 /home/www/vvveb/demo/plugins/seo/modules/breadcrumbs/breadcrumbs.php(77): Vvveb\Plugins\Seo\Modules\Breadcrumbs\Breadcrumbs->post()
#4 [internal function]: Vvveb\Plugins\Seo\Modules\Breadcrumbs\Breadcrumbs->product()
#5 /home/www/vvveb/demo/system/event.php(105): call_user_func_array()
#6 /home/www/vvveb/demo/app/controller/product/product.php(198): Vvveb\System\Event::trigger()
#7 [internal function]: Vvveb\Controller\Product\Product->index()
#8 /home/www/vvveb/demo/system/core/frontcontroller.php(252): call_user_func()
#9 /home/www/vvveb/demo/system/core/frontcontroller.php(322): Vvveb\System\Core\FrontController::call()
#10 /home/www/vvveb/demo/system/core/frontcontroller.php(396): Vvveb\System\Core\FrontController::redirect()
#11 /home/www/vvveb/demo/system/core/startup.php(521): Vvveb\System\Core\FrontController::dispatch()
#12 /home/www/vvveb/demo/index.php(122): Vvveb\System\Core\start()
#13 /home/www/vvveb/demo/index.php(168): Vvveb\saveCache()
#14 /home/www/vvveb/demo/public/index.php(28): include('...')
#15 {main}
    [code] => Array
        (
            [0] =>  namespace Vvveb\Plugins\Seo\Modules\Breadcrumbs;

            [2] => 

            [3] => use Vvveb\System\Core\View;

            [4] => use Vvveb\System\Event;

            [5] => 

            [6] => if (! defined('V_VERSION')) {

            [7] => 	die('Invalid request!');

            [8] => }

            [9] => 

            [10] => /**

            [11] =>  * Breadcrumbs: BreadcrumbList JSON-LD + view vars for themes.

            [12] =>  * Listens on the same content events as Seo\App so trails match the page.

            [13] =>  */

            [14] => class Breadcrumbs {

            [15] => 	function app(): void {

            [16] => 		Event::on('Vvveb\Controller\Content\Post', 'index:after', __CLASS__, [$this, 'post'], 2000);

            [17] => 		Event::on('Vvveb\Controller\Content\Page', 'index:after', __CLASS__, [$this, 'post'], 2000);

            [18] => 		Event::on('Vvveb\Controller\Product\Product', 'index:after', __CLASS__, [$this, 'product'], 2000);

            [19] => 		Event::on('Vvveb\Controller\Content\Category', 'index:after', __CLASS__, [$this, 'taxonomy'], 2000);

            [20] => 		Event::on('Vvveb\Controller\Product\Category', 'index:after', __CLASS__, [$this, 'taxonomy'], 2000);

            [21] => 	}

            [22] => 

            [23] => 	public static function baseUrl(): string {

            [24] => 		if (class_exists('\Vvveb\Plugins\Seo\Modules\Sitemap\Sitemap')) {

            [25] => 			return \Vvveb\Plugins\Seo\Modules\Sitemap\Sitemap::baseUrl();

            [26] => 		}

            [27] => 		$scheme = \Vvveb\isSecure() ? 'https' : 'http';

            [28] => 

            [29] => 		return rtrim($scheme . '://' . SITE_URL . (V_SUBDIR_INSTALL ? V_SUBDIR_INSTALL : '') . SITE_PATH, '/');

            [30] => 	}

            [31] => 

            [32] => 	/** Build ordered crumbs: each [name, url|null]. */

            [33] => 	public static function crumbs(array $trail): array {

            [34] => 		$out = [];

            [35] => 		$pos = 1;

            [36] => 		foreach ($trail as $crumb) {

            [37] => 			$item = ['@type' => 'ListItem', 'position' => $pos++, 'name' => mb_substr(strip_tags((string)($crumb['name'] ?? '')), 0, 200)];	 // <==

            [38] => 			if (! empty($crumb['url'])) {

            [39] => 				$item['item'] = $crumb['url'];

            [40] => 			}

            [41] => 			$out[] = $item;

            [42] => 		}

            [43] => 

            [44] => 		return $out;

            [45] => 	}

            [46] => 

            [47] => 	public static function jsonLd(array $trail): ?string {

            [48] => 		$items = self::crumbs($trail);

            [49] => 		if (count($items) < 2) {

            [50] => 			return null;

            [51] => 		}

            [52] => 

            [53] => 		return json_encode(['@context' => 'https://schema.org', '@type' => 'BreadcrumbList', 'itemListElement' => $items], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

            [54] => 	}

            [55] => 

            [56] => 	protected function emit(array $trail) {

            [57] => 		$view = View::getInstance();

            [58] => 		$view->seo = $view->seo ?? [];

            [59] => 		$view->breadcrumbs = $trail;

            [60] => 		if ($json = self::jsonLd($trail)) {

            [61] => 			$view->seo['schema']['breadcrumbs'] = $json;

            [62] => 		}

            [63] => 	}

            [64] => 

            [65] => 	function post($content, $languageContent, $language, $slug) {

            [66] => 		$post = $content[$language] ?? [];

            [67] => 		if (! empty($post['name'])) {

            [68] => 			$base = self::baseUrl();

            [69] => 			$this->emit([['name' => 'Home', 'url' => $base . '/'], ['name' => $post['name'], 'url' => null]]);

            [70] => 		}

            [71] => 

            [72] => 		return [$content, $languageContent, $language, $slug];

            [73] => 	}

            [74] => 

            [75] => 	function product($content, $languageContent, $language, $slug) {

            [76] => 		return $this->post($content, $languageContent, $language, $slug);

            [77] => 	}

            [78] => 

            [79] => 	function taxonomy($taxonomy, $type) {

            [80] => 		if (! empty($taxonomy['name'])) {

            [81] => 			$base = self::baseUrl();

            [82] => 			$trail = [['name' => 'Home', 'url' => $base . '/']];

            [83] => 			if (! empty($taxonomy['parent_name'])) {

            [84] => 				$trail[] = ['name' => $taxonomy['parent_name'], 'url' => null];

            [85] => 			}

            [86] => 			$trail[] = ['name' => $taxonomy['name'], 'url' => null];

            [87] => 			$this->emit($trail);

            [88] => 		}

            [89] => 

            [90] => 		return [$taxonomy, $type];

            [91] => 	}

            [92] => }

        )

)