Перейти к содержанию
Официальный форум поддержки Simpla

Kami

Пользователь
  • Публикаций

    559
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Kami

  1. В 12.12.2023 в 08:32, phukortsin сказал:

    Именно объемный. В Вашем же посте вижу с ходу тому два подтверждения. Первое:

     

    Пользователю куда удобнее иметь инструкцию в виде "в файле таком-то вставить код такой-то в место такое-то". То, что Вы в таком виде не написали, говорит о том, что это требует трудозатрат, и куда больше чем пара минут. 

    Второе:

    Потому как если выискать только такие комменты и сделать только по ним изменения, то с гарантией работать не будет. Потому как есть еще несколько иные комменты, и даже ДВУХ типов.  Добавочно вспоминаем и тезис об аккуратности...

    Так как решение я дал бесплатно, то тут либо голову включать человеку, либо тут найти специалиста кто это всё перенесет исправно. В целом дал более чем полное решение)

  2. 5 часов назад, phukortsin сказал:

    Все это можно делать по аналогии. Но код не совсем простой и довольно объемный, требуется аккуратность...

    Ну не прям объемный, но да, внимательно надо отнестись к запросам при копировании связанных.

  3. 15 часов назад, megauser сказал:

    Есть связанные товары в товаре, А кто делал для обычной страницы товары?

    На форуме что то не нашел ничего похожего.

    Чтоб не разжевывать скинул полные файлы, ищи в коде комменты 

    /*related_page_products*/
    
    /*/related_page_products*/

    Запрос в базу

    CREATE TABLE `s_related_page_products` (
      `page_id` int(11) NOT NULL,
      `related_id` int(11) NOT NULL,
      `position` int(11) NOT NULL,
      PRIMARY KEY (`page_id`,`related_id`),
      KEY `position` (`position`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    api/Pages.php

    <?php
    /**
     * Simpla CMS
     *
     * @copyright	2011 Denis Pikusov
     * @link		http://simplacms.ru
     * @author		Denis Pikusov
     *
     */
    require_once('Simpla.php');
    class Pages extends Simpla
    {
    	/*
    	*
    	* Функция возвращает страницу по ее id или url (в зависимости от типа)
    	* @param $id id или url страницы
    	*
    	*/
    	public function get_page($id)
    	{
    		if(gettype($id) == 'string')
    			$where = $this->db->placehold(' WHERE url=? ', $id);
    		else
    			$where = $this->db->placehold(' WHERE id=? ', intval($id));
    		
    		$query = "SELECT id, url, header, name, meta_title, meta_description, meta_keywords, body, menu_id, position, visible
    		          FROM __pages $where LIMIT 1";
    		$this->db->query($query);
    		return $this->db->result();
    	}
    	
    	/*
    	*
    	* Функция возвращает массив страниц, удовлетворяющих фильтру
    	* @param $filter
    	*
    	*/
    	public function get_pages($filter = array())
    	{	
    		$menu_filter = '';
    		$visible_filter = '';
    		$pages = array();
    		if(isset($filter['menu_id']))
    			$menu_filter = $this->db->placehold('AND menu_id in (?@)', (array)$filter['menu_id']);
    		if(isset($filter['visible']))
    			$visible_filter = $this->db->placehold('AND visible = ?', intval($filter['visible']));
    		
    		$query = "SELECT id, url, header, name, meta_title, meta_description, meta_keywords, body, menu_id, position, visible
    		          FROM __pages WHERE 1 $menu_filter $visible_filter ORDER BY position";
    	
    		$this->db->query($query);
    		
    		foreach($this->db->results() as $page)
    			$pages[$page->id] = $page;
    			
    		return $pages;
    	}
    	/*
    	*
    	* Создание страницы
    	*
    	*/	
    	public function add_page($page)
    	{	
    		$query = $this->db->placehold('INSERT INTO __pages SET ?%', $page);
    		if(!$this->db->query($query))
    			return false;
    		$id = $this->db->insert_id();
    		$this->db->query("UPDATE __pages SET position=id WHERE id=?", $id);	
    		return $id;
    	}
    	
    	/*
    	*
    	* Обновить страницу
    	*
    	*/
    	public function update_page($id, $page)
    	{	
    		$query = $this->db->placehold('UPDATE __pages SET ?% WHERE id in (?@)', $page, (array)$id);
    		if(!$this->db->query($query))
    			return false;
    		return $id;
    	}
    	
    	/*
    	*
    	* Удалить страницу
    	*
    	*/	
    	public function delete_page($id)
    	{
    		if(!empty($id))
    		{
                /*related_page_products*/
    			$this->db->query('DELETE FROM __related_page_products WHERE page_id=?', intval($id));
                /*/related_page_products*/
    
    			$query = $this->db->placehold("DELETE FROM __pages WHERE id=? LIMIT 1", intval($id));
    			if($this->db->query($query))
    				return true;
    		}
    		return false;
    	}	
    
    		/*related_page_products*/
    		function get_related_products($page_id = array())
    		{
    			if(empty($page_id))
    				return array();
    	
    			$page_id_filter = $this->db->placehold('AND page_id in(?@)', (array)$page_id);
    					
    			$query = $this->db->placehold("SELECT page_id, related_id, position
    						FROM __related_page_products
    						WHERE 
    						1
    						$page_id_filter   
    						ORDER BY position       
    						");
    			
    			$this->db->query($query);
    			return $this->db->results();
    		}
    		
    		// Функция возвращает связанные товары
    		public function add_related_product($page_id, $related_id, $position=0)
    		{
    			$query = $this->db->placehold("INSERT IGNORE INTO __related_page_products SET page_id=?, related_id=?, position=?", $page_id, $related_id, $position);
    			$this->db->query($query);
    			return $related_id;
    		}
    		
    		// Удаление связанного товара
    		public function delete_related_product($page_id, $related_id)
    		{
    			$query = $this->db->placehold("DELETE FROM __related_page_products WHERE page_id=? AND related_id=? LIMIT 1", intval($page_id), intval($related_id));
    			$this->db->query($query);
    		}
    		/*/related_page_products*/
    	
    	/*
    	*
    	* Функция возвращает массив меню
    	*
    	*/
    	public function get_menus()
    	{
    		$menus = array();
    		$query = "SELECT * FROM __menu ORDER BY position";
    		$this->db->query($query);
    		foreach($this->db->results() as $menu)
    			$menus[$menu->id] = $menu;
    		return $menus;
    	}
    	
    	/*
    	*
    	* Функция возвращает меню по id
    	* @param $id
    	*
    	*/
    	public function get_menu($menu_id)
    	{	
    		$query = $this->db->placehold("SELECT * FROM __menu WHERE id=? LIMIT 1", intval($menu_id));
    		$this->db->query($query);
    		return $this->db->result();
    	}
    	
    }

    simpla/PageAdmin.php

    <?PHP
    require_once('api/Simpla.php');
    class PageAdmin extends Simpla
    {	
    	public function fetch()
    	{	
    		$page = new stdClass;
    		/*related_page_products*/
            $related_products = array();
            /*/related_page_products*/
    
    		if($this->request->method('POST'))
    		{
    			$page->id = $this->request->post('id', 'integer');
    			$page->name = $this->request->post('name');
    			$page->header = $this->request->post('header');
    			$page->url = trim($this->request->post('url'));
    			$page->meta_title = $this->request->post('meta_title');
    			$page->meta_keywords = $this->request->post('meta_keywords');
    			$page->meta_description = $this->request->post('meta_description');
    			$page->body = $this->request->post('body');
    			$page->menu_id = $this->request->post('menu_id', 'integer');
    			$page->visible = $this->request->post('visible', 'boolean');
    	
    			## Не допустить одинаковые URL разделов.
    			if(($p = $this->pages->get_page($page->url)) && $p->id!=$page->id)
    			{			
    				$this->design->assign('message_error', 'url_exists');
    			}
    			else
    			{
    				if(empty($page->id))
    				{
    	  				$page->id = $this->pages->add_page($page);
    	  				$page = $this->pages->get_page($page->id);
    	  				$this->design->assign('message_success', 'added');
      	    		}
      	    		else
      	    		{
      	    			$this->pages->update_page($page->id, $page);
    	  				$page = $this->pages->get_page($page->id);
    	  				$this->design->assign('message_success', 'updated');
       	    		}
    
    				/*related_page_products*/
        			if(is_array($this->request->post('related_products')))
        			{
        				foreach($this->request->post('related_products') as $p)
        				{
        					$rp[$p] = new stdClass;
        					$rp[$p]->page_id = $page->id;
        					$rp[$p]->related_id = $p;
        				}
        				$related_products = $rp;
        			}
                    $query = $this->db->placehold('DELETE FROM __related_page_products WHERE page_id=?', $page->id);
       	    		$this->db->query($query);
     	  		    if(is_array($related_products))
    	  		    {
    	  		    	$pos = 0;
    	  		    	foreach($related_products  as $i=>$related_product)
       	    				$this->pages->add_related_product($page->id, $related_product->related_id, $pos++);
      	    		}
                    /*/related_page_products*/
    			}
    		}
    		else
    		{
    			$id = $this->request->get('id', 'integer');
    			/*related_page_products*/
                $related_products = (!$id ? array() : $this->pages->get_related_products(array('page_id'=>$id)));
    			/*/related_page_products*/
    
    			if(!empty($id))
    				$page = $this->pages->get_page(intval($id));			
    			else
    			{
    				$page->menu_id = $this->request->get('menu_id');
    				$page->visible = 1;
    			}
    		}	
    
    		/*related_page_products*/
            if(!empty($related_products))
    		{
    			foreach($related_products as &$r_p)
    				$r_products[$r_p->related_id] = &$r_p;
    			$temp_products = $this->products->get_products(array('id'=>array_keys($r_products)));
    			foreach($temp_products as $temp_product)
    				$r_products[$temp_product->id] = $temp_product;
    		
    			$related_products_images = $this->products->get_images(array('product_id'=>array_keys($r_products)));
    			foreach($related_products_images as $image)
    			{
    				$r_products[$image->product_id]->images[] = $image;
    			}
    		}
            $this->design->assign('related_products', $related_products);
            /*/related_page_products*/
    
    		$this->design->assign('page', $page);
    		
     	  	$menus = $this->pages->get_menus();
    		$this->design->assign('menus', $menus);
    		
    	    // Текущее меню
    	    if(isset($page->menu_id))
    	  		$menu_id = $page->menu_id; 
    	  	if(empty($menu_id) || !$menu = $this->pages->get_menu($menu_id))
    	  	{
    	  		$menu = reset($menus);
    	  	}
    	 	$this->design->assign('menu', $menu);
     	  	return $this->design->fetch('page.tpl');
    	}
    	
    }

    simpla/design/html/page.tpl

    {capture name=tabs}
    	{if in_array('pages', $manager->permissions)}
    	{foreach $menus  as $m}
    		<li {if $m->id == $menu->id}class="active"{/if}><a href='index.php?module=PagesAdmin&menu_id={$m->id}'>{$m->name}</a></li>
    	{/foreach}
    	{/if}
    {/capture}
    {if $page->id}
    {$meta_title = $page->name scope=parent}
    {else}
    {$meta_title = 'Новая страница' scope=parent}
    {/if}
    {* Подключаем Tiny MCE *}
    {include file='tinymce_init.tpl'}
    {* On document load *}
    {literal}
    <script src="design/js/jquery/jquery.js"></script>
    <script src="design/js/jquery/jquery-ui.min.js"></script>
    {*related_page_products*}
    <script src="design/js/autocomplete/jquery.autocomplete-min.js"></script>
    {*related_page_products*}
    <script>
    $(function() {
    
    	/*related_page_products*/
        // Удаление связанного товара
    	$(".related_products a.delete").live('click', function() {
    		 $(this).closest("div.row").fadeOut(200, function() { $(this).remove(); });
    		 return false;
    	});
        // Добавление связанного товара 
    	var new_related_product = $('#new_related_product').clone(true);
    	$('#new_related_product').remove().removeAttr('id');
    	$("input#related_products").autocomplete({
    		serviceUrl:'ajax/search_products.php',
    		minChars:0,
    		noCache: false, 
    		onSelect:
    			function(suggestion){
    				$("input#related_products").val('').focus().blur(); 
    				new_item = new_related_product.clone().appendTo('.related_products');
    				new_item.removeAttr('id');
    				new_item.find('a.related_product_name').html(suggestion.data.name);
    				new_item.find('a.related_product_name').attr('href', 'index.php?module=ProductAdmin&id='+suggestion.data.id);
    				new_item.find('input[name*="related_products"]').val(suggestion.data.id);
    				if(suggestion.data.image)
    					new_item.find('img.product_icon').attr("src", suggestion.data.image);
    				else
    					new_item.find('img.product_icon').remove();
    				new_item.show();
    			},
    		formatResult:
    			function(suggestions, currentValue){
    				var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');
    				var pattern = '(' + currentValue.replace(reEscape, '\\$1') + ')';
      				return (suggestions.data.image?"<img align=absmiddle src='"+suggestions.data.image+"'> ":'') + suggestions.value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
    			}
    
    	});
    	// Сортировка связанных товаров
    	$(".sortable").sortable({
    		items: "div.row",
    		tolerance:"pointer",
    		scrollSensitivity:40,
    		opacity:0.7,
    		handle: '.move_zone'
    	});
        /*/related_page_products*/
    
    	// Автозаполнение мета-тегов
    	menu_item_name_touched = true;
    	meta_title_touched = true;
    	meta_keywords_touched = true;
    	meta_description_touched = true;
    	url_touched = true;
    	
    	if($('input[name="menu_item_name"]').val() == generate_menu_item_name() || $('input[name="name"]').val() == '')
    		menu_item_name_touched = false;
    	if($('input[name="meta_title"]').val() == generate_meta_title() || $('input[name="meta_title"]').val() == '')
    		meta_title_touched = false;
    	if($('input[name="meta_keywords"]').val() == generate_meta_keywords() || $('input[name="meta_keywords"]').val() == '')
    		meta_keywords_touched = false;
    	if($('textarea[name="meta_description"]').val() == generate_meta_description() || $('textarea[name="meta_description"]').val() == '')
    		meta_description_touched = false;
    	if($('input[name="url"]').val() == generate_url())
    		url_touched = false;
    		
    	$('input[name="name"]').change(function() { menu_item_name_touched = true; });
    	$('input[name="meta_title"]').change(function() { meta_title_touched = true; });
    	$('input[name="meta_keywords"]').change(function() { meta_keywords_touched = true; });
    	$('textarea[name="meta_description"]').change(function() { meta_description_touched = true; });
    	$('input[name="url"]').change(function() { url_touched = true; });
    	
    	$('input[name="header"]').keyup(function() { set_meta(); });
    });
    function set_meta()
    {
    	if(!menu_item_name_touched)
    		$('input[name="name"]').val(generate_menu_item_name());
    	if(!meta_title_touched)
    		$('input[name="meta_title"]').val(generate_meta_title());
    	if(!meta_keywords_touched)
    		$('input[name="meta_keywords"]').val(generate_meta_keywords());
    	if(!meta_description_touched)
    	{
    		descr = $('textarea[name="meta_description"]');
    		descr.val(generate_meta_description());
    		descr.scrollTop(descr.outerHeight());
    	}
    	if(!url_touched)
    		$('input[name="url"]').val(generate_url());
    }
    function generate_menu_item_name()
    {
    	name = $('input[name="header"]').val();
    	return name;
    }
    function generate_meta_title()
    {
    	name = $('input[name="header"]').val();
    	return name;
    }
    function generate_meta_keywords()
    {
    	name = $('input[name="header"]').val();
    	return name;
    }
    function generate_meta_description()
    {
    	if(typeof(tinyMCE.get("body")) =='object')
    	{
    		description = tinyMCE.get("body").getContent().replace(/(<([^>]+)>)/ig," ").replace(/(\&nbsp;)/ig," ").replace(/^\s+|\s+$/g, '').substr(0, 512);
    		return description;
    	}
    	else
    		return $('textarea[name=body]').val().replace(/(<([^>]+)>)/ig," ").replace(/(\&nbsp;)/ig," ").replace(/^\s+|\s+$/g, '').substr(0, 512);
    }
    function generate_url()
    {
    	url = $('input[name="header"]').val();
    	url = url.replace(/[\s]+/gi, '-');
    	url = translit(url);
    	url = url.replace(/[^0-9a-z_\-]+/gi, '').toLowerCase();	
    	return url;
    }
    function translit(str)
    {
    	var ru=("А-а-Б-б-В-в-Ґ-ґ-Г-г-Д-д-Е-е-Ё-ё-Є-є-Ж-ж-З-з-И-и-І-і-Ї-ї-Й-й-К-к-Л-л-М-м-Н-н-О-о-П-п-Р-р-С-с-Т-т-У-у-Ф-ф-Х-х-Ц-ц-Ч-ч-Ш-ш-Щ-щ-Ъ-ъ-Ы-ы-Ь-ь-Э-э-Ю-ю-Я-я").split("-")   
    	var en=("A-a-B-b-V-v-G-g-G-g-D-d-E-e-E-e-E-e-ZH-zh-Z-z-I-i-I-i-I-i-J-j-K-k-L-l-M-m-N-n-O-o-P-p-R-r-S-s-T-t-U-u-F-f-H-h-TS-ts-CH-ch-SH-sh-SCH-sch-'-'-Y-y-'-'-E-e-YU-yu-YA-ya").split("-")   
     	var res = '';
    	for(var i=0, l=str.length; i<l; i++)
    	{ 
    		var s = str.charAt(i), n = ru.indexOf(s); 
    		if(n >= 0) { res += en[n]; } 
    		else { res += s; } 
        } 
        return res;  
    }
    </script>
    
    <!--related_page_products-->
    <style>
    .autocomplete-suggestions{
    background-color: #ffffff; width: 100px; overflow: hidden;
    border: 1px solid #e0e0e0;
    padding: 5px;
    }
    .autocomplete-suggestions .autocomplete-suggestion{cursor: default;}
    .autocomplete-suggestions .selected { background:#F0F0F0; }
    .autocomplete-suggestions div { padding:2px 5px; white-space:nowrap; }
    .autocomplete-suggestions strong { font-weight:normal; color:#3399FF; }
    </style>
    <!--/related_page_products-->
    {/literal}
    {if $message_success}
    <!-- Системное сообщение -->
    <div class="message message_success">
    	<span class="text">{if $message_success == 'added'}Страница добавлена{elseif $message_success == 'updated'}Страница обновлена{/if}</span>
    	<a class="link" target="_blank" href="../{$page->url}">Открыть страницу на сайте</a>
    	{if $smarty.get.return}
    	<a class="button" href="{$smarty.get.return}">Вернуться</a>
    	{/if}
    	
    	<span class="share">		
    		<a href="#" onClick='window.open("http://vkontakte.ru/share.php?url={$config->root_url|urlencode}/{$page->url|urlencode}&title={$page->name|urlencode}&description={$page->body|urlencode}&noparse=false","displayWindow","width=700,height=400,left=250,top=170,status=no,toolbar=no,menubar=no");return false;'>
      		<img src="{$config->root_url}/simpla/design/images/vk_icon.png" /></a>
    		<a href="#" onClick='window.open("http://www.facebook.com/sharer.php?u={$config->root_url|urlencode}/{$page->url|urlencode}","displayWindow","width=700,height=400,left=250,top=170,status=no,toolbar=no,menubar=no");return false;'>
      		<img src="{$config->root_url}/simpla/design/images/facebook_icon.png" /></a>
    		<a href="#" onClick='window.open("http://twitter.com/share?text={$page->name|urlencode}&url={$config->root_url|urlencode}/{$page->url|urlencode}&hashtags={$page->meta_keywords|replace:' ':''|urlencode}","displayWindow","width=700,height=400,left=250,top=170,status=no,toolbar=no,menubar=no");return false;'>
      		<img src="{$config->root_url}/simpla/design/images/twitter_icon.png" /></a>
    	</span>
    	
    </div>
    <!-- Системное сообщение (The End)-->
    {/if}
    {if $message_error}
    <!-- Системное сообщение -->
    <div class="message message_error">
    	<span class="text">{if $message_error == 'url_exists'}Страница с таким адресом уже существует{/if}</span>
    	<a class="button" href="">Вернуться</a>
    </div>
    <!-- Системное сообщение (The End)-->
    {/if}
    <!-- Основная форма -->
    <form method=post id=product enctype="multipart/form-data">
    	<input type=hidden name="session_id" value="{$smarty.session.id}">
    	<div id="name">
    		<input class="name" name=header type="text" value="{$page->header|escape}"/> 
    		<input name=id type="hidden" value="{$page->id|escape}"/> 
    		<div class="checkbox">
    			<input name=visible value='1' type="checkbox" id="active_checkbox" {if $page->visible}checked{/if}/> <label for="active_checkbox">Активна</label>
    		</div>
    	</div> 
    		<!-- Параметры страницы -->
    		<div class="block">
    			<ul>
    				<li><label class=property>Название пункта в меню</label><input name="name" class="simpla_inp" type="text" value="{$page->name|escape}" /></li>
    				<li><label class=property>Меню</label>	
    					<select name="menu_id">
    				   		{foreach $menus as $m}
    				        	<option value='{$m->id}' {if $page->menu_id == $m->id}selected{/if}>{$m->name|escape}</option>
    				    	{/foreach}
    					</select>		
    				</li>
    			</ul>
    		</div>
    		<!-- Параметры страницы (The End)-->
    	<!-- Левая колонка свойств товара -->
    	<div id="column_left">
    			
    		<!-- Параметры страницы -->
    		<div class="block layer">
    			<h2>Параметры страницы</h2>
    			<ul>
    				<li><label class=property>Адрес</label><div class="page_url">/</div><input name="url" class="page_url" type="text" value="{$page->url|escape}" /></li>
    				<li><label class=property>Заголовок</label><input name="meta_title" class="simpla_inp" type="text" value="{$page->meta_title|escape}" /></li>
    				<li><label class=property>Ключевые слова</label><input name="meta_keywords" class="simpla_inp" type="text" value="{$page->meta_keywords|escape}" /></li>
    				<li><label class=property>Описание</label><textarea name="meta_description" class="simpla_inp"/>{$page->meta_description|escape}</textarea></li>
    			</ul>
    		</div>
    		<!-- Параметры страницы (The End)-->		
    			
    	</div>
    	<!-- Левая колонка свойств товара (The End)--> 
    
    		<!-- Правая колонка свойств товара -->	
    		<div id="column_right">
    		{*related_page_products*}
            <div class="block layer">
    			<h2>Связанные товары</h2>
    			<div id=list class="sortable related_products">
    				{foreach from=$related_products item=related_product}
    				<div class="row">
    					<div class="move cell">
    						<div class="move_zone"></div>
    					</div>
    					<div class="image cell">
    					<input type=hidden name=related_products[] value='{$related_product->id}'>
    					<a href="{url id=$related_product->id}">
    					<img class=product_icon src='{$related_product->images[0]->filename|resize:35:35}'>
    					</a>
    					</div>
    					<div class="name cell">
    					<a href="{url id=$related_product->id}">{$related_product->name}</a>
    					</div>
    					<div class="icons cell">
    					<a href='#' class="delete"></a>
    					</div>
    					<div class="clear"></div>
    				</div>
    				{/foreach}
    				<div id="new_related_product" class="row" style='display:none;'>
    					<div class="move cell">
    						<div class="move_zone"></div>
    					</div>
    					<div class="image cell">
    					<input type=hidden name=related_products[] value=''>
    					<img class=product_icon src=''>
    					</div>
    					<div class="name cell">
    					<a class="related_product_name" href=""></a>
    					</div>
    					<div class="icons cell">
    					<a href='#' class="delete"></a>
    					</div>
    					<div class="clear"></div>
    				</div>
    			</div>
    			<input type=text name=related id='related_products' class="input_autocomplete" placeholder='Выберите товар чтобы добавить его'>
    		</div>
    
    		<input class="button_green button_save" type="submit" name="" value="Сохранить" />
            {*/related_page_products*}
    		</div>
    		<!-- Правая колонка свойств товара (The End)--> 
    		
    	<!-- Описагние товара -->
    	<div class="block layer">
    		<h2>Текст страницы</h2>
    		<textarea name="body"  class="editor_large">{$page->body|escape}</textarea>
    	</div>
    	<!-- Описание товара (The End)-->
    	<input class="button_green button_save" type="submit" name="" value="Сохранить" />
    	
    </form>
    <!-- Основная форма (The End) -->

    view/PageView.php

    <?PHP
    /**
     * Simpla CMS
     *
     * @copyright 	2011 Denis Pikusov
     * @link 		http://simplacms.ru
     * @author 		Denis Pikusov
     *
     * Этот класс использует шаблон page.tpl
     *
     */
    require_once('View.php');
    class PageView extends View
    {
    	function fetch()
    	{
    		$url = $this->request->get('page_url', 'string');
    		$page = $this->pages->get_page($url);
    		
    		// Отображать скрытые страницы только админу
    		if(empty($page) || (!$page->visible && empty($_SESSION['admin'])))
    			return false;
    		
    		$this->design->assign('page', $page);
    		$this->design->assign('meta_title', $page->meta_title);
    		$this->design->assign('meta_keywords', $page->meta_keywords);
    		$this->design->assign('meta_description', $page->meta_description);
    
    		/*related_page_products*/
            // Связанные товары
    		$related_ids = array();
    		$related_products = array();
    		foreach($this->pages->get_related_products($page->id) as $p)
    		{
    			$related_ids[] = $p->related_id;
    			$related_products[$p->related_id] = null;
    		}
    
    		if(!empty($related_ids))
    		{
    			foreach($this->products->get_products(array('id'=>$related_ids, 'visible'=>1)) as $p)
    				$related_products[$p->id] = $p;
    			
    			$related_products_images = $this->products->get_images(array('product_id'=>array_keys($related_products)));
    			foreach($related_products_images as $related_product_image)
    				if(isset($related_products[$related_product_image->product_id]))
    					$related_products[$related_product_image->product_id]->images[] = $related_product_image;
    			$related_products_variants = $this->variants->get_variants(array('product_id'=>array_keys($related_products), 'in_stock'=>1));
    			foreach($related_products_variants as $related_product_variant)
    			{
    				if(isset($related_products[$related_product_variant->product_id]))
    				{
    					$related_products[$related_product_variant->product_id]->variants[] = $related_product_variant;
    				}
    			}
    			foreach($related_products as $id=>$r)
    			{
    				if(is_object($r))
    				{
    					$r->image = &$r->images[0];
    					$r->variant = &$r->variants[0];
    				}
    				else
    				{
    					unset($related_products[$id]);
    				}
    			}
    			$this->design->assign('related_products', $related_products);
    		}
            /*/related_page_products*/
    		
    		return $this->design->fetch('page.tpl');
    	}
    }

    В шаблоне сайта

    {if $related_products}
    {foreach $related_products as $related_product}
    Тут товары
    {/foreach}
    {/if}

    Ну и в api/Products.php

    в функции

    delete_product

    добавить удаление товара из связанных при его удалении

    			/*related_page_products*/
                $this->db->query("DELETE FROM __related_page_products where related_id=?", $id);
                /*/related_page_products*/

     

  4. Может кому пригодится, понадобилось сделать фильтр клиента по цене, найти товары у которых цена больше, меньше или равна.

     

    в simpla/design/html/products.tpl

    {* По цене *}
    <form method="get">
        <div id="price">
            <input type="hidden" name="module" value="ProductsAdmin">
            <select name="price_comparison">
                <option value="" {if empty($price_comparison)}selected{/if}>Выберите</option>
                <option value="equal" {if $price_comparison == "equal"}selected{/if}>Равно</option>
                <option value="less" {if $price_comparison == "less"}selected{/if}>Меньше</option>
                <option value="greater" {if $price_comparison == "greater"}selected{/if}>Больше</option>
            </select>
            <input class="price_input" type="text" name="price" placeholder="Введите цену" value="{$price|escape}" />
            <input class="price_button" type="submit" value="Найти"/>
        </div>
    </form>

    В simpla/design/css/style.css

    #price {
    	display: flex;
        flex-direction: column;
        gap: 15px;
        padding: 15px 15px;
        border: 1px solid #343434;
        margin-bottom: 30px;
    }

    В ProductsAdmin.php

    $price_comparison = $this->request->get('price_comparison');
    $price = $this->request->get('price');
    
    if (!empty($price)) {
        $filter['price'] = $price;
        $this->design->assign('price', $price);
    }
    
    if (!empty($price_comparison)) {
        $filter['price_comparison'] = $price_comparison;
    	$this->design->assign('price_comparison', $price_comparison);
    }

    В Api/products.php

    в 2 функции get_products и count_products  ставим новый фильтр

    		/*фильтр по цене*/
    		$price_filter = '';
    		/*фильтр по цене*/

    Далее сам фильтр

    		/*фильтр по цене*/
    		if (isset($filter['price_comparison']) && isset($filter['price'])) {
    			$price_comparison = $filter['price_comparison'];
    			$price_value = intval($filter['price']);
    		
    			switch ($price_comparison) {
    				case 'equal':
    					$price_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.price = ? LIMIT 1)', $price_value);
    					break;
    				case 'less':
    					$price_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.price < ? LIMIT 1)', $price_value);
    					break;
    				case 'greater':
    					$price_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.price > ? LIMIT 1)', $price_value);
    					break;
    			}
    		}
    
    		/*фильтр по цене*/

    и в общем $query добавляем

    $price_filter

     Вдруг кому пригодится.

  5. В 23.08.2023 в 08:14, phukortsin сказал:

    Значит, не хватает серверу ресурсов.

     

    Ну вот проблема ресурсов решена, а вот всё равно фид грузится 5 минут ти ложится с ошибкой. То есть даже 5 минут не хватает чтоб выполнить запрос к 20 к товарам со свойствами т.д.

    Как вы выходили из ситуации? пилить фид?

  6. 11 минут назад, phukortsin сказал:

    В этом и соль что уже все прописал

     

        location / {

            proxy_pass http://127.0.0.1:81;

            proxy_redirect http://127.0.0.1:81/ /;

            include /etc/nginx/proxy_params;

            fastcgi_read_timeout 300;

            fastcgi_send_timeout 300;

            proxy_read_timeout 300;

        }

    И сервер перезагружал, всё равно - 1 минуту выполняет и уходит в 504 ошибку.

  7. В 18.08.2023 в 08:50, phukortsin сказал:

    Такой проблемы у большинства типовых сайтов НЕТ. При 20 тыс обычно товаров фид формируется легко и быстро. Если у Вас не работает, то это, скорее всего, проблема слабого сервера. Если нет желания/возможности перейти на лучший тарифный план, то работать надо индивидуально. Сначала выяснять причину (основные варианты - не хватает ресурсов MySQL или не хватает оперативной памяти сервера). А потом уже придумывать хитрости, чтобы обойти нехватку ресурсов...

    Например, если причина затыка в нехватке ресурсов MySQL, то можно выходить из положения, как намекнул shooroop - делать подряд несколько запросов с ограничением, например, по 4000 записей...

    Вообще в логах странная ошибка. 2023/08/22 05:36:52 [error] 145577#145577: *2 upstream timed out (110: Connection timed out) while reading response header from upstream,

    Сервер ложится с ошибкой 504 Gateway Time-out

    Сам сервер выделенный и с хорошим железом, стоит fast panel

  8. https://keram.ru/catalog/plitka/

    Есть сайт пример по продаже плитки.

    У него есть категории товары так скажем по дефолту.

    Но помимо этого есть еще коллекции

    https://keram.ru/catalog/plitka/?display=manufactureCollection

    в коллекции могут быть плитки разных категорий, как настенная плитка , так и плинтус. 

    Вопрос, как лучше создать структуру и связать ее с базовой simpla? 

    Создать отдельную сущность collections по аналогии с категориями?

  9. 17 часов назад, phukortsin сказал:

    Если совсем просто, то добавить к заказу поле по аналогии с комментарием. И пусть туда пишут "в пятницу после обеда".  Или даже вообще пусть в комментарии записывают дату - тогда вообще ничего делать не надо...

    а в целом был опыт создании бронирования на simpla?

  10. 1 час назад, phukortsin сказал:

    У Вас фактически магазин продает не ТОВАР, а АРЕНДУ. Чтобы выглядело достойно, надо значительно перерабатывать функционал, просто и легко вряд ли получится. Надо, видимо, иметь расписание сеансов, и продавать билеты на сеансы. Вариантов разработки есть много разных. А если все же хотите просто, то записывать дату аренды надо в новое поле, как уже было сказано. Может, к заказу, а может, к покупке...

    Согласен, по идее надо прям делать чтоб в одну баню не забронировали 5-6 человек . Но просят просто выбор даты, дальше как обычно ручной труд. 

    В общем если не совсем колхоз, то я думал хранить выбранные дату и время в сессии а потом уже при заказе записывать в pushares таблицу.  Пока только такая идея

  11. В 09.06.2023 в 23:36, shooroop сказал:

     

    Какая дата? Дата создания товара, или дата оформления заказ или дата добавления товара в корзину или может у вас дата своя к примеру годности товара....

    Своя дата, не хотелось бы городить лишний функционал, по сути есть дата которую выбираем на странице товара, аренда бани по сути и кладем в корзину, создавать варианты с датами конечно не получится, т.к. дата постоянно меняется, вот и думаю куда ее записывать чтоб в корзине товар с датой хранился

  12. В 02.06.2023 в 09:26, phukortsin сказал:

    Нестандартно запрограммировать все требующееся.

    http://simpla-tuning.ru/dobavlenie-v-korzinu-srazu-neskolkih-variantov

     

     

    У меня не стандартно немного сделано, что есть еще дата и время которые надо добавить к товару. 

    С вариантами то разобраться можно 

    if (is_array($simpla->request->get('variants'))) {
        $variants = $simpla->request->get('variants');
        foreach ($variants as $s => $v) {
            $simpla->cart->add_item($s, $v);
        }
    }

    А вот как сделать чтоб еще дата куда то записывалась? к товару который берут? 

  13. Есть немного нестандартный вопрос.

    Есть у товара 2 варианта

    Как правильней сделать чтоб 

    Можно было выбрать кол-во для каждого из двух вариантов и при клике в корзину чтоб оба товара сразу ушли в корзину с тем же количеством что выбрали.

  14. В 04.03.2023 в 11:31, Drake777 сказал:

    да, имел в виду авторов самого Okay. Полностью согласен с тем, что владельцы сайтов опасаются такого отношения. И был недавно удивлен, когда обратились с заявкой сделать именно на Okay проект

    а что мешает делать проекты на окай? как по мне так Виталий забивает болт на клиентов еще до начала СВО, поэтому что изменилось?

    Берем окай, он с открытым кодом, свежие версии на github пушат, так что не вижу проблем поддерживать и пилить для России.

    Ну а теряет позиции потому что в Украине сейчас наверное не до интернет торговли.

  15. Кто сталкивался с таким интересным подходом добавлять контрагентов?

    Кто то до меня придумал у клиента такую фичу,

    			if(empty($order->user_id))
                $order->user_id = $order->id;

    В целом костыль норм, но потом если человек регается и user_id совпадает с номером заказа, то происходит каша в контрагентах при выгрузке в Мой склад.

    Кто сталкивался и какое решение было оптимальным? 

  16. 11 часов назад, alexivchenko сказал:

    Существуют зарезервированные символы, которые имеют зарезервированные значения, это разделители — :/?#[]@— и суб-ограничители — !$&'()*+,;=

    Существует также набор символов, называемых незарегистрированными символами — буквенно-цифровыми и -._~— которые не подлежат кодированию.

    https://habr.com/ru/post/232385/?ysclid=l8kubsbx19485130653


    https://datatracker.ietf.org/doc/html/rfc3986

    Ну по логике 

    RewriteRule ^\*$ / [R=301,L]

    Должно редиректить с https://site.ru/* на https://site.ru

    Но по итогу я получаю 

    https://site.ru/?module=PageView&page_url=*

  17. 11 часов назад, Kosjak76 сказал:

    По поводу чего?

    Придумали проблему - и давай чего-то придумывать)))

    https://www.wildberries.ru/?

    Вот, например, и не мешает никому)

    Проблема в том что все CMS отдают нормально 404, а Simpla показывает главную.

    Как вариант можно было бы сделать редирект на нормальную главную. Но пока все методы выдают циклический редирект.

×
×
  • Создать...