120, 'main_page_lenta' =>120, 'main-page-main-view-glob' => 60, //600 'main-page-main-view' => 60, 'topic-news-##' => 3600 ]; private static function processPersons(string $body) { $re = '/(\W+)<\/a>/m'; $res = preg_replace_callback($re,function (array $matches): string { $person = Person::find()->andWhere(['alias'=>ArrayHelper::getValue($matches,'2')])->one(); if($person instanceof Person){ switch (ArrayHelper::getValue($matches,'1')) { case "person-inject": return \Yii::$app->view->render("/news/view/inject-person-as-widget", ["person" => $person]); break; default: return \Yii::$app->view->render("/news/view/inject-person-as-link", ["person" => $person]); } } return ArrayHelper::getValue($matches,0); }, $body); return $res; } private static function processBody($body,$model) { $counter = 0; $re = '/<(?:p|h2).*>(.*)<\/(?:p|h2)>/msU'; $res = preg_replace_callback($re,function (array $matches) use(&$counter,$model): string { $counter++; if($counter==2 && Yii::$app->deviceDetect->isMobile() && !$model->inTopic(158)) return $matches[0].Yii::$app->controller->renderPartial("@app/views/_etc/banners/adfinityInContent"); if($counter==3 && !Yii::$app->deviceDetect->isMobile() && !$model->inTopic(158)) return $matches[0].Yii::$app->controller->renderPartial("@app/views/_etc/banners/desktopInContent"); return $matches[0]; },$body); return $res; } private static function processGalleriesInjects(string $body, News $post) { $re = '/

(##_gallery-(\d+)##)<\/p>/mU'; $body = preg_replace( $re, '\1', $body ); $re = '/##_gallery-(\d+)##/mU'; $res = preg_replace_callback($re,function (array $matches) use($post): string { $gallery = \app\models\front\Gallery::findOne(['id'=>ArrayHelper::getValue($matches,1)]); if($gallery instanceof \app\models\front\Gallery) { return \Yii::$app->view->render("/news/view/inject-gallery-x",["gallery"=>$gallery, "model"=>$post]); } else { return ""; } },$body); return $res; } public function getUrl($full = false):string { if(count($this->topics)>0){ $topic = Transliterator::toUrl($this->topics[0]->title)."/"; } else{ $topic = ""; } switch ($this->type){ // case 6: // return "https://old.amic.ru/long/{$this->id}/"; // break; default: $base = Url::base('https'); $alias = trim( $this->alias ); if( $alias == '' ){ $alias = Transliterator::toUrl($this->title); } if( isset( $this->dt_pub ) && strtotime( $this->dt_pub ) > strtotime('2023-01-27 15:00:00') ){ return ($full ? $base : "")."/news/".$alias."-".$this->id; } return ($full ? $base : "")."/news/".$topic.$alias."-".$this->id; } } public function getMainPic(){ } /** * @return Image */ public function getPreview($type="webp"):Image{ return Image::findOne($this->id,$type,$this->photo_name); } public function getOld():ActiveQuery { return $this->hasOne(OldNews::class,['alias'=>'alias']); } /** * @return ActiveQuery */ public function getCommentsAll(): ActiveQuery { if($this->comments=="Y"){ return $this->hasMany(Comments::class,['news_id'=>"id"])->andWhere(['visible'=>'Y']); } return $this->hasMany(Comments::class,['news_id'=>"id"])->andWhere(0); } public static function getMainView(){ return self::find()->joinWith("topics t")->andWhere(["t.id"=>[33,]]); } public static function getNH(){ return self::find()->andWhere(['active'=>'Y', 'NH'=>['Y','F']])->andWhere(['between', 'dt_pub', date("Y-m-d H:i:00",time()-2678400*3 ) , date("Y-m-d H:i:00")])->orderBy(["NH"=>SORT_DESC,"dt_pub"=>SORT_DESC])->limit(1); } public static function getPartnersNews(){ return self::find()->joinWith("topics t")->andWhere(["t.id"=>[34,]]); } public static function getMainOfWeek(){ return self::find()->joinWith("topics t")->andWhere(["t.id"=>[35,]]); } public function getDatePub(){ return $this->dt_pub; } public function getPublishedAt(){ if($this->dt_pubdt_pub))." ".mb_strtolower(Transliterator::month(date("n",strtotime($this->dt_pub)))) .date(" Y, H:i", strtotime($this->dt_pub)) ; } else { $diff = ceil((time() - strtotime($this->dt_pub))/60); //В минутах if($diff<=60){ return Transliterator::plural($diff,['минуту','минуты', 'минут'],true,'только что','минуту')." назад"; } else { $diff = (int)floor($diff/60); return Transliterator::plural($diff,['час','часа', 'часов'],true,'только что','час')." назад"; } } } public function getPublishedNorm(){ return date("d",strtotime($this->dt_pub))." ".mb_strtolower(Transliterator::month(date("n",strtotime($this->dt_pub)))) .date(" Y, H:i", strtotime($this->dt_pub)) ; } public function isPhotosOnNews( $dt_pub = null ) { if( $this->inscription) return true; if( isset( $this->photo_title ) && stripos($this->photo_title, 'amic.ru') !== false ) return true; if( $dt_pub ){ $dt_pub = strtotime($dt_pub); }else{ $dt_pub = strtotime($this->dt_pub); } if( $dt_pub >= strtotime(Yii::$app->params['delPhotoB']) && $dt_pub < strtotime(Yii::$app->params['delPhotoE']) ) return false; return true; } public function renderBody() { $post = $this; $device = Yii::$app->deviceDetect->isMobile()?"mobile":"desktop"; return \Yii::$app->cache->getOrSet("post-body8-".$this->id."-".$device,function () use ($post){ $body = $post->text; //Нужно воткнуть рекламу после второго абзаца $body = self::processBody($body,$this); // $body = self::processSingleImg($body); $body = $this->DateDelImg($body); $body = self::processTextImg($body); $body = self::processInjects($body); $body = self::processAudio($body); if( $this->isPhotosOnNews($post->getDatePub() ) ){ $body = self::processSlider($body, $post); //old slider $body = self::processGalleriesInjects($body, $post); } $body = self::processYoutube($body); $body = self::processIframe($body); $body = self::processSpecialFormats($body); $body = self::processPersons($body); $body = self::processTest($body); $body = self::processApiImg($body); $body = self::ShowPollsWidget($body); $body = self::ShowPreportWidget($body); if( $post->inscription == 0 ) $body = self::processAhref($body); // кроме комерческих return $body; },YII_ENV_DEV?1:60); } public static function processApiImg($text) { return str_replace( 'https://api.amic.ru', '', $text); } public static function processTest($text) { $text = str_replace("\xc2\xa0", ' ', $text); $text = str_replace(['

 

','

'], "\c", $text); $text = trim( $text ); $text = str_replace( "\c", "

", $text); $text = str_replace( 'href="http://tel=', 'href="tel:', $text ); return $text; } public static function processSpecialFormats($text) { if( stripos($text, 'class="juxtapose"') !== false ){ $str = ' '; return $text.$str; } return $text; } /* * Парсинг для старых слайдеров (очень старых) */ public static function processSlider($text, $obj) { if( $obj->uid == '' ) return $text; $dir = '/images/items/'.$obj->uid; $files1 = @scandir(Yii::getAlias('@webroot').$dir.'/thumbnails/',0); $old_title = ( trim($obj->old_gallery_title) != '' )?''.trim($obj->old_gallery_title).'':''; if( $files1 == false || count( $files1 ) < 4){ $files1 = @scandir(Yii::getAlias('@webroot').$dir.'/images/thumbnails/', 0); if( $files1 === false || count( $files1 ) == 0){ return $text; }else{ $i=1; ob_start(); foreach( $files1 as $file ){ if( preg_match('/^.*\.(gif|jpe?g|png)/i', $file ) ){ $str = @file_get_contents( Yii::getAlias('@webroot').$dir.'/info/'.$file.'.json' ); if( $str == false ){ $str='{"title":"","copyrate":""}'; } $js_title = json_decode( $str ); $str_title = ( $js_title->title == '' )?$old_title:$js_title->title;//iconv('UTF-8','cp1251',$js_title->title); $str_title .= ( $js_title->copyrate == '' )?'':'
'.$js_title->copyrate.''; $add_cap = ($str_title != '')?", caption: '".$str_title."'":''; ?> {img: '/images/', thumb: '/images/thumbnails/' }, {img: '/big/', thumb: '/thumbnails/'}, '; } ?> acache; $c->set('fotorama', true); ?> ]+)href=\"([^>]*\/files\/)(.+)\.mp3\"([^>]*)>([^<]*)<\/a>/i'; $res = preg_replace_callback($re,function (array $matches): string { $title = isset($matches[5])?$matches[5]:''; if( !strstr( $matches[1], "download") ) { $url = $matches[2]; $audio = ''."\n"; if( file_exists( $_SERVER['DOCUMENT_ROOT'].''.$matches[2].$matches[3].'.mp3.ogg' ) ){ $audio .= ''."\n"; } return \Yii::$app->view->render("/news/view/audio",["audio"=>$audio, "title"=>$title]); } else { return ArrayHelper::getValue($matches,0); } },$text); return $res; } /* * Спрятать внешнии ссылки от поисковиков * Псевдо SEO * */ public static function processAhref($text) { $re = '/]+href=\"(https?:\/\/[^"]*)\".*>/Ui'; $res = preg_replace_callback($re,function (array $matches): string { $mydomain = \Yii::$app->params['mydomain']; foreach( $mydomain as $find ){ if( stripos( $matches[1], $find) !== false ) return $matches[0]; } $ret = str_replace( $matches[1], "/go/?u=".urlencode($matches[1]), $matches[0] ); return $ret; },$text); return $res; } public static function processInjects($text) { $re = '/##news_(.*)##/mU'; $res = preg_replace_callback($re,function (array $matches): string { $post = News::findOne(['uid'=>ArrayHelper::getValue($matches,1)]); if($post instanceof News) { return \Yii::$app->view->render("/news/view/inject",["post"=>$post]); } else { return ""; } },$text); if( strlen($res) != strlen($text) ) return $res; $re = "|]+>.[^<]*|U"; $res = preg_replace_callback($re,function (array $matches): string { @$xml = simplexml_load_string( str_replace( ' ', '', ArrayHelper::getValue($matches,0) ), 'SimpleXMLElement', LIBXML_NOCDATA ); if( $xml ){ $attributes =$xml->attributes(); if( $attributes['class'] == 'insinject' || $attributes['id'] == "inject" ){ $r = preg_match( "/^https?:\/\/(.*)\/(.*)\/(\d+)\/$/i", $attributes['url'], $aa ); $id = 0; if( $r && ($aa[1] == 'www.amic.ru' || $aa[1] == Yii::$app->request->serverName) && $aa[3]*1 > 0 ){ // old style inject $id = $aa[3]*1; } $r = preg_match( "/^https?:\/\/(.*)\/.*(\d+)\/?$/Ui", $attributes['url'], $aa ); if( $r && ($aa[1] == Yii::$app->request->serverName || $aa[1] == 'www.amic.ru')&& $aa[2]*1 > 0 ){ // new style inject $id = $aa[2]*1; } $r = preg_match( '/^https?:\/\/(.*)\/person\/(.*)\/?$/Ui', $attributes['url'], $aa ); if( $r && ($aa[1] == Yii::$app->request->serverName || $aa[1] == 'www.amic.ru')&& $aa[2] != '' ){ $person = \app\models\Person::findOne(['alias'=>$aa[2]]); if( ( !$person instanceof Person ) || $person->show == 'N' ){ return ""; } return \Yii::$app->view->render("/news/view/injectp",["post"=>$person]); } if( $id ){ //$attributes['type'] to do $post = News::findOne(['id'=>$id]); if($post instanceof News) { if( $attributes['type'] == 1 ){ return \Yii::$app->view->render("/news/view/inject1",["post"=>$post]); }else if( $attributes['type'] == 2 ){ return \Yii::$app->view->render("/news/view/inject2",["post"=>$post]); }else{ return \Yii::$app->view->render("/news/view/inject",["post"=>$post]); } } else { return "Битый инжект"; } } } } return ArrayHelper::getValue($matches,0); },$text); return $res; } public static function processIframe($text) //https://youtu.be/sfzX5fMaSj4 -> https://www.youtube.com/embed/sfzX5fMaSj4 { $re = '/(]*>).*(<\/iframe>)/Ui'; $text = preg_replace_callback($re,function (array $mt): string { //print_r($mt); // libxml_use_internal_errors(true); $content = $mt[0]; $content = str_replace( '&', '#-#', $content); $HXML=''; $doc = new DOMDocument('1.0','UTF-8'); // нормализация xml @$doc->loadHTML($HXML.$content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOCDATA); // $doc->encoding = 'UTF-8'; $doc->normalizeDocument(); $content = $doc->saveXML($doc->documentElement); $content = html_entity_decode($content); $content = str_replace( '', '', $content); $content = str_replace( '', '', $content); $content = str_replace( '', '', $content); $xml = simplexml_load_string( $content, 'SimpleXMLElement',LIBXML_HTML_NODEFDTD | LIBXML_NOXMLDECL |LIBXML_HTML_NOIMPLIED ); if( $xml ){ $attrs = $attributes =$xml->attributes(); //print_r( $attrs ); $xmlo = simplexml_load_string( $HXML.'', 'SimpleXMLElement', LIBXML_NOCDATA ); // var_dump($attrs); if( !Yii::$app->deviceDetect->isMobile() ){ if( $attrs['src'] && strpos( $attrs['src'], 'vk.com' ) !== false ) $fixedRatio = '16/9'; } foreach( $attrs as $key=>$attr ){ if( $key == 'height'){ $height = preg_replace('/[\D]/', '', $attr); if( $height == 0 ) $height = 0.1; $attr = 'auto'; } if( $key == 'width'){ $width = preg_replace('/[\D]/', '', $attr); if( strpos($attr, '%') !== false ){ $width = $width*720/100; } $attr = '100%'; } if( isset($height) && isset($width) ){ if( isset( $fixedRatio ) ){ $ratio = $fixedRatio; }else{ $ratio = round( $width/$height, 2 ); } if( !isset($xmlo->attributes()->style) ){ $xmlo->addAttribute('style', 'width:100%; aspect-ratio:'.$ratio); }else{ $xmlo->attributes()->style = $xmlo->attributes()->style.'width:100%; aspect-ratio:'.$ratio; } unset($height); unset($width); } @$xmlo->addAttribute($key, $attr); } return str_replace( '#-#', '&', preg_replace('|^\<\?xml version="1.0" encoding="UTF-8"\?\>\n|i', '',$xmlo->asXML()) ); } return $mt[0]; }, $text); return $text; } /* * Парсинг короткой ссылки ютуба * */ public static function processYoutube($text) //https://youtu.be/sfzX5fMaSj4 -> https://www.youtube.com/embed/sfzX5fMaSj4 { return str_replace( 'https://youtu.be/', 'https://www.youtube.com/embed/', $text ); } public static function processSingleImg($text) { $re = '/(<[p|a][^>]*>)()(<\/[p|a]>)/i'; $res = preg_replace_callback($re,function (array $matches): string { $img = ArrayHelper::getValue($matches,2); $a = array(); $title = ''; if( preg_match( '/title="(.*)"/mU', $img, $a) ){ $title = '
'.$a[1].'
'; } if( $title && preg_match( '/rel-credit="(.*)"/mU', $img, $a) ){ if( trim( $a[1] ) != '' ){ $title = str_replace('', ' фото: '.$a[1].'', $title); } } if( $title && preg_match( '/longdesc="(.*)"/mU', $img, $a) ){ $title = str_replace('', ' '.$a[1].'', $title); } $style = ''; $a = array(); if( preg_match( '/style="(.*)"/mU', $img, $a) ){ $style = $a[1]; $style = str_replace('height', 'data-height', $style); $img = str_replace('margin', 'margin-block', $img); } //class='picture-cont-16x9' $pic= "
{$img} {$title}
"; return str_replace('','div>',ArrayHelper::getValue($matches,3)); },$text); return $res; } public function DateDelImg($text) { $obj = $this; $re = '/(]*>)/i'; $text = preg_replace_callback($re,function (array $mt) use($obj): string { /* После этой даты не выводить фото до подтверждения юриста */ if( !$this->isPhotosOnNews( $obj->getDatePub() ) ){ $bad = '/images/default.jpg'; return ''; }; return $mt[0]; }, $text); return $text; } public static function processTextImg($text) { $text = str_replace('src="http://', 'src="https://', $text); //в качестве бреда $text = str_replace( 'publib/gimage.php?image=/', '', $text ); // очень очень старый движ $re = '/(]*>)/i'; $text = preg_replace_callback($re,function (array $mt): string { //print_r($mt); libxml_use_internal_errors(true); $staic = false; $content = $mt[0]; $content = str_replace('&','$%$',$content); $HXML=''; $doc = new DOMDocument('1.0','UTF-8'); // нормализация xml $doc->loadHTML($HXML.$content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOCDATA); // $doc->encoding = 'UTF-8'; $doc->normalizeDocument(); $content = $doc->saveXML($doc->documentElement); $content = html_entity_decode($content); $content = str_replace( '', '', $content); $content = str_replace( '', '', $content); $content = str_replace( '', '', $content); $xml = simplexml_load_string( $content, 'SimpleXMLElement',LIBXML_HTML_NODEFDTD | LIBXML_NOXMLDECL |LIBXML_HTML_NOIMPLIED ); if( $xml ){ $attrs = $attributes =$xml->attributes(); //print_r( $attrs ); $xmlo = simplexml_load_string( $HXML.'', 'SimpleXMLElement', LIBXML_NOCDATA ); // var_dump($attrs); $url = isset($attrs->longdesc)?$attrs->longdesc:''; foreach( $attrs as $key=>$attr ){ if( $key == 'height'){ $xmlo->addAttribute('data-height', $attr); continue; } if( $key == 'style'){ $attr = trim( $attr, " ;\r\n" ); //$attr = str_replace(' ', '', $attr); $css = explode( ";", $attr ); $stylesd = array(); $stylesi = array(); foreach( $css as $attrx ){ list($key1, $value) = explode( ":", $attrx ); $key1 = trim($key1); if( $key1 == 'height' || $key1 == '' ){ continue; }elseif( stristr( 'margin', $key1 ) !== false ){ $stylesd[] = "{$key1}:{$value}"; }elseif( $key1 == 'float' ){ $stylesd[] = "{$key1}:{$value}"; }elseif( $key1 == 'width' ){ //$value = preg_replace("/[^0-9\-.]/", '', $value); if( preg_replace("/[^0-9\-.]/", '', $value) > 720-150 ){ $value = '100%'; } $stylesd[] = "{$key1}:{$value}"; $stylesi[] = "{$key1}:100%"; $stylesd[] = "display:block"; }elseif( $key1 && $value){ $stylesd[] = "{$key1}:{$value}"; if( $key1 == 'margin-right' || $key1 == 'margin-left' ) $value = 0; if( $key1 != 'margin' ) { $stylesi[] = "{$key1}:{$value}"; } } } $attr = implode('; ', $stylesd); $xmlo->addAttribute($key, $attr); $attr = implode('; ', $stylesi); $xmlo->picture->img->addAttribute($key, $attr); } if( $key == 'class'){ if( $attr == 'staic' ){ $staic = true; } } $title = ''; if( $key == 'title'){ $title = str_replace( '"', "'", trim($attr)); $xmlo->picture->img->addAttribute($key, $title); /* if( isset( $attrs['rel-credit'] ) && trim($attrs->rel-credit) != ''){ $attr = trim($attrs->{rel-credit})?$attrs->rel-credit:''; $title .= ' фото: '.$attr; } */ }else{ if( $xmlo->picture->img->$key && trim($key) != ''){ $xmlo->picture->img->$key = $attr; }else{ if( trim($key) != '' ) @$xmlo->picture->img->addAttribute($key, $attr); } } if( $title ){ $e = $xmlo->addChild('span', $title); // class="image-title" style="margin-top: 20px;" $e->addAttribute('class',"image-title image-title-fix"); //$e->addAttribute('style',"margin-top: 20px;"); if( $url ){ $e1 = $e->addChild('a', $url); $e1->addAttribute('href', $url); } } } if( isset( $xmlo->attributes()->style ) ){ $s = $xmlo->attributes()->style .= ';overflow: hidden;'; unset($xmlo->attributes()->style); $xmlo->addAttribute('style',$s ); }else{ $xmlo->addAttribute('style', 'overflow: hidden;'); } $str = str_replace('$%$','&',preg_replace('|^\<\?xml version="1.0" encoding="UTF-8"\?\>\n|i', '',$xmlo->asXML())); if( $staic ){ $str = str_replace( '100%', 'auto', $str); } return $str; } return $mt[0]; }, $text); return $text; } public function behaviors() { $keys = array_keys(self::$keysCache); return [ 'CachedBehavior' => [ 'class' => CachedBehavior::class, 'cache_key' => $keys, ] ]; } public static function find0() { return parent::find(); } public static function find() { return parent::find()->orderBy(["dt_pub"=>SORT_DESC]); } /** * @return ActiveQuery */ public function getGalleries() { return $this->hasMany(Gallery::class,['post_id'=>'id']); } public function getYoutubeEmbedLink(){ $data = parse_url($this->embed_url); if(is_array($data)){ switch (ArrayHelper::getValue($data,'host')){ case "vk.com": $path = preg_split( '/[-_]/', ArrayHelper::getValue($data,'path') ); if( isset($path[1]) && isset($path[2]) && is_numeric($path[1]) && is_numeric($path[2]) ){ return "https://vk.com/video_ext.php?oid=-{$path[1]}&id={$path[2]}"; } return ''; break; default: switch (ArrayHelper::getValue($data,'path')){ case "/watch": $re = '/v=(.*)/m'; preg_match_all($re, ArrayHelper::getValue($data,'query'), $matches, PREG_SET_ORDER, 0); $video_id = '/'.ArrayHelper::getValue($matches,'0.1'); break; default: $video_id = ArrayHelper::getValue($data,'path',''); } } return "https://www.youtube.com/embed".$video_id; } return ""; } public function inTopic(int $topic_id): bool { return (bool)$this->getTopicRelations()->andWhere(['topic_id'=>$topic_id])->count(); } public static function ShowPollsWidget( $str ){ preg_match_all( "|]+>.[^<]*|U", $str, $a, PREG_SET_ORDER ); foreach ( $a as $item ){ $xml = @simplexml_load_string( str_replace( ' ', '', $item[0] ), 'SimpleXMLElement', LIBXML_NOCDATA ); if( $xml ){ $attributes =$xml->attributes(); if( $attributes['id'] == 'widgetpolls' ){ // старый стиль url $r = preg_match( "/^https?:\/\/(.*)\/(.*)\/widget\/(\d+)\/$/i", trim($attributes['url']), $aa ); if( $r && $aa[3]*1 > 0 ){ if( $aa[2] == 'polls' ){ $str = str_replace( $item[0], self::ShowPollsHtml( str_replace( ['http://www.amic.ru'],[''],$attributes['url']), $attributes['type'] ), $str ); } }else{ $r = preg_match( "/^https?:\/\/(.*)\/inquirer\/(\d+)$/i", trim($attributes['url']), $aa ); if( $r && $aa[2]*1 > 0 ){ $str = str_replace( $item[0], self::ShowPollsHtml( "/polls/widget/".$aa[2]*1, $attributes['type'] ), $str ); } } } } } return $str; } public static function ShowPollsHtml( $url, $type ){ static $i = 0; $url = trim($url); ob_start(); ?>
]+>.[^<]*|U", $str, $a, PREG_SET_ORDER ); foreach ( $a as $item ){ $xml = @simplexml_load_string( str_replace( ' ', '', $item[0] ), 'SimpleXMLElement', LIBXML_NOCDATA ); if( $xml ){ $attributes =$xml->attributes(); if( $attributes['id'] == 'widgetgallery' ){ // старый стиль url $r = preg_match( "/^https?:\/\/(.*)\/(.*)\/(\d+)\/$/i", trim($attributes['url']), $aa ); if( $r && $aa[3]*1 > 0 ){ if( $aa[2] == 'photo' ){ $str = str_replace( $item[0], self::ShowPreportHtml( "/photo/widget/".$aa[3]*1, $attributes['type'] ), $str ); $c = Yii::$app->acache; $c->set('fotorama', true); } } } } } return $str; } public static function ShowPreportHtml( $url, $type ){ static $i = 0; ob_start(); ?>