abushyk

Модераторы
  • Публикации

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

  • Посещение

  • Days Won

    269

Изменения репутации

  1. Like
    abushyk получил репутацию от Smoke в Шаблон realia - пожалуйста, помогите с меню категорий [Решено]   
    Тут нужно сделать следующее.
    Для менюшек вставленных вручную
    1. нужны файлы языков в зоне шаблона. не скажу, что 100%, но в реалии они уже могут быть. это папка /template/frontend/realia/language. Если ее нет, то просто создайте ее и внутри нее создайте подпапки по вашим рабочим языкам - /template/frontend/realia/language/en  /template/frontend/realia/language/ru.
    2. В каждой из этих папок должен лежать файл с именем dictionary.ini для хранения языковых меток.
    3. внутри этот файл выглядит как-то так:
    LT_NEWS="News" LT_FOR_USER="For users" LT_USEFUL="Usefull" LT_SPECIAL="Special" метка="текстовое_значение_на_соотв_языке"
    4. Берете все ваши пункты меню из примера и проставляете метки
    LT_MN_HOME="Главная" LT_MN_ABCOMP="О компании" LT_MN_OUTCITYEST="Иногородняя недвижимость" напр для русского. названия меток не принципиальны, но я бы рекомендовал ставить префикс LT_ что бы потом знать где метка описана. таким префиксом я обозначаю метки из папки шаблона в отличии от меток из приложений или системных.
    5. Сами текстовые слова в getTemplateMenu текстовые надписи меняем на 
    Multilanguage::_('LT_MN_HOME', '_template'); c указанием подходящих меток.
    ... array('id'=>0,'title'=>Multilanguage::_('LT_MN_HOME', '_template'),'position'=>'behind'), ...  
    Для менюшек вставленных из заготовленных меню и Контент - Меню
    Я внес некоторые изменения в файл сборщика меню для реалии http://pastebin.com/XAr8uPvR для функции getTemplateMenu (правки на лету, код сырой. может сразу не завестись. я тут, если кто-то будет пробовать, пишите сюда)
    От вас требуется задать для пунктов меню соотвествующие языковые поля-клоны.
    Кеширование убрано из индивидуальных сессий в общий файл-хранилище.
  2. Like
    abushyk получил репутацию от Chernetskiy в Выгрузка Yandex.Realty   
    $ret='<room-space><value>'.implode('</value><unit>кв.м</unit></room-space><room ====>
    $rs.='<room-space><value>'.implode('</value><unit>кв.м</unit></room-space><room .............................
    А от мы неведомой переменной $ret сообщаем нашу строку с хмл и потому в вывод она не приходит))
  3. Like
    abushyk получил репутацию от TopRaN в [HOWTO] Локальный grid_manager   
    Центральным местом, которое в 90% случаев обрабатывает запросы на извлечение нескольких записей-объявлений (всякого рода сетки-списки, в том числе и спецпредложениях в боковых колонках и забор данных для нанесения на карту), является файл /apps/system/lib/frontend/grid/grid_constructor.php - или Конструктор списка (КС).
    В нем много разного функционала, но самый часто востребованный лежит в двух функциях transformGridData - подготовка данных к выводу и prepareRequestParams - обработка параметров поиска.
    prepareRequestParams выполняет все операции связанные с тем, что бы превратить фильровочные переменные запроса, переданные в Конструктор списка, в части запроса к БД. Она имеет встроенную обработку некоторого числа параметров, но для расширения функционала иногда необходимо добавить свои. prepareRequestParams  НЕ обрабатывает параметры запроса прямо из строки браузера. Все параметры с веб-интерфейса перехватываются отдельной функцией, нормализуются и только тогда передаются в prepareRequestParams.
    transformGridData адаптирует результат выборки из БД к удобоваримому виду. Поскольку результатом выборки списка являются строки из БД, то именно эта функция трансформирует значения указанные ключем, например поля select_box и select_by_query  в текстовые значения. Эта функция так же умеет обрабатывать сама некоторые "стандартные" поля, например географические - country_id, region_id,... street_id, currency_id и все поля типа select_box. "Превращение" в текст остальные ссылочных полей необходимо реализовывать самому
    Как создать для шаблона локальный Grid_manager
    1. Переопределением метода в шаблоне (ручное) - устаревший
    В файле /template/frontend/имя_вашего_шаблона/main/main.php смотрим, есть ли функция __construct(). Если нет, то создаем ее внутри декларации class frontend_main extends SiteBill_Krascap {} в виде 
    public function __construct(){ parent::__construct(); require SITEBILL_DOCUMENT_ROOT.'/template/frontend/'.$this->getConfigValue('theme').'/main/grid/local_grid_constructor.php'; $this->_setGridConstructor(new Local_Grid_Constructor()); } 2. Переопределением метода в шаблоне (автоматическое) - устаревший
    В файле /settings.php.ini добавляем секцию описания локального Конструктора списков
    [GridConstructor] path='/main/grid/local_grid_constructor.php' name='Local_Grid_Constructor' Первая строка - имя секции
    вторая - путь к файлу локального Конструктора списка от корня шаблона
    третья - задекларированное имя класса локального Конструктора списка
    3. Настроечное переопределение - используйте, по возможности, именно этот вариант локализации
    Указываем в Настройки  - Общее галочку Использовать локальный Конструктор списка (classic_local_grid)
    Отличие последнего метода от остальных в том, что в нем имя класса конструктора и имя файла в котором он расположен должны быть соответственно Local_Grid_Constructor и template/frontend/имя_шаблона/grid/local_grid_constructor.php и никакими иначе.
    =============================================================================================
    Одним из этих способов мы указываем шаблону, что нужно использовать для построения списков наш измененный Конструктор списков. Но теперь нам необходимо создать его.
    Для этого нам нужно создать файл по адресу указанному в require_once для первого способа, в path для второго и в /template/frontend/имя_шаблона/grid/local_grid_constructor.php для третьего.
    Базовое наполнение этого файла будет иметь вид:
    class Local_Grid_Constructor extends Grid_Constructor { } Уже после этого локальный КС будет работать, но так как он пока пуст, то он просто, как транслятор, будет передавать заказы в стандартный КС. Для того, что бы добавить что-то свое, нам нужно внести в него изменения.
    1. Добавляем подхват текстового значения для поля типа select_by_query
    Поскольку это операция трансформации из ключевого значения в текстовое, то нам понадобится функция transformGridData . Так как остальные параметры нам нужны и мы просто хотим добавить своего, то мы делаем свою функцию с вызовом родительской
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info);/*используем "стандартный" вызов для выполнения привычных действий*/ /*тут мы можем сделать что-то свое с данными*/ return $data; /*возвращаемся в текущий процесс исполнения*/ } Итак у нас в объявлении есть поле station_id связывающее объект с некоторой станцией из внешней таблицы station в которой станции разложены по строкам вида station_id, name. Так как в данных объявления при выборке мы имеем только ключ станции, а хотим получить именно ее имя и штатный трансформатор за нас этого не делает, то мы проиводим следующее
    foreach($data as $k=>$d){ if ( $d['station_id'] > 0 ) { $data[$k]['station'] = $data_model->get_string_value_by_id('station', 'station_id', 'name', $d['station_id'], true); }else{ $data[$k]['station']=''; } } Либо
    $station_ids=array(); foreach($data as $k=>$d){ $station_ids[intval($d['station_id'])]=intval($d['station_id']); } if(!empty($station_ids)){ $DBC=DBC::getInstance(); $query='SELECT `station_id`, `name` FROM '.DB_PREFIX.'_station WHERE station_id IN ('.implode(',', $station_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $station_ids[$ar['station_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($station_ids[intval($d['station_id'])])){ $data[$k]['station']=$station_ids[intval($d['station_id'])]; }else{ $data[$k]['station']=''; } } первый способ короче, но второй на больших количествах записей более продуктивен и более удобен, если нужно получить сложные названия текстового значения, например сцепить с названием станции еще и какой-то другой признак из свойств самой станции.
    Для select_by_query второй вложенности, например если нужно получить имя застройщика, которое является свойством объекта ЖК, с которым связан объект, первый вариант уже не проходит. Т.е. использовать его конечно можно, но количество дополнительных действий сразу перекрывает сложность второго способа. Поэтому используем сразу второй.
    $complex_ids=array(); foreach($data as $k=>$d){ $complex_ids[intval($d['complex_id'])]=intval($d['complex_id']); } if(!empty($complex_ids)){ $DBC=DBC::getInstance(); $query='SELECT d.`name`, c.`complex_id` FROM '.DB_PREFIX.'_complex c LEFT JOIN '.DB_PREFIX.'_developer d USING (developer_id) WHERE complex_id IN ('.implode(',', $complex_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $complex_ids[$ar['complex_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($complex_ids[intval($d['complex_id'])])){ $data[$k]['developer']=$complex_ids[intval($d['complex_id'])]; }else{ $data[$k]['developer']=''; } } Очевидно, что принцип схожий и разница заключается только в мелочах вроде запроса на выборку связанного объекта. При чем, в зависимости от сложности желаемого к получению текстового значения будет меняться и сложность запроса, которая запросто может распасться на несколько.
    В итоге наш локальный КС будет выглядеть таким образом:
    <?php class Local_Grid_Constructor extends Grid_Constructor { public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info);/*используем "стандартный" вызов для выполнения привычных действий*/ /*тут мы можем сделать что-то свое с данными*/ $complex_ids=array(); foreach($data as $k=>$d){ $complex_ids[intval($d['complex_id'])]=intval($d['complex_id']); } if(!empty($complex_ids)){ $DBC=DBC::getInstance(); $query='SELECT `complex_id` FROM '.DB_PREFIX.'_complex WHERE complex_id IN ('.implode(',', $station_ids).')'; $query='SELECT d.`name`, c.`complex_id` FROM '.DB_PREFIX.'_complex c LEFT JOIN '.DB_PREFIX.'_developer d USING (developer_id) WHERE complex_id IN ('.implode(',', $complex_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $complex_ids[$ar['complex_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($complex_ids[intval($d['complex_id'])])){ $data[$k]['developer']=$station_ids[intval($d['complex_id'])]; }else{ $data[$k]['developer']=''; } } return $data; /*возвращаемся в текущий процесс исполнения*/ } } 2. Получаем дату в красивом формате
    Иногда нужно подготовить дату под вывод, что бы не мучаться с однотипными действиями в каждом шаблоне. Например подготовим дату добавления в виде "12 ноябра 2013 года".
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); $months=array( '1'=>'января', '2'=>'февраля', '3'=>'марта', '4'=>'апреля', '5'=>'мая', '6'=>'июня', '7'=>'июля', '8'=>'августа', '9'=>'сентября', '10'=>'октября', '11'=>'ноября', '12'=>'декабря', ); foreach($data as $k=>$d){ $month=date('n', $d['date_added']); $data[$k]['pretty_date']=date('j', $d['date_added']).' '.$months[date('n', $d['date_added'])].' '.$months[date('Y', $d['date_added'])]; } return $data; } и в поле pretty_date в шаблоне у нас будет искомая строка
    3. День добавления
    Подготовим дату добавления, что бы она показывала было ли добавлено объявление сегодня, вчера или в другой день.
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); $now=date('dmY'); $yesterday=date('dmY', time()-24*3600); foreach($data as $k=>$d){ if($now==date('dmY', strtotime($d['date_added']))){ $data[$k]['pretty_adddate']='сегодня'; }elseif($yesterday==date('dmY', strtotime($d['date_added']))){ $data[$k]['pretty_adddate']='вчера'; }else{ $data[$k]['pretty_adddate']=date('d.m.Y', strtotime($d['date_added'])); } } return $data; } Этот вариант можно скомбинировать с предыдущим.
    4. Форматирование адресной строки
    Форматируем строку адреса для списка вида "Нижний Тагил (Заводской), Лермонтова, 12" [Город (Район), Улица, Дом]
    protected function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); foreach($data as $k=>$d){ $addrline=array(); if($d['city']!=''){ if($d['district']!=''){ $addrline[]=$d['city'].' ('.$d['district'].')'; }else{ $addrline[]=$d['city']; } } if($d['street']!=''){ $addrline[]=$d['street']; if($d['number']!=''){ $addrline[]=$d['number']; } } if(!empty($addrline)){ $data[$k]['pretty_address']=implode(', ', $addrline); }else{ $data[$k]['pretty_address']=''; } } return $data; }  
  4. Like
    abushyk изменил репутацию Chernetskiy в Выгрузка Yandex.Realty   
    Попутно обратил внимание в admin.php, примерно 1455 строка, непонятно что в формировании параметра window-view делает параметр floor-covering, может чего не понимаю?
    if(isset($form_data_shared['window_view']) && isset($data_item['window_view']) && $data_item['window_view']!=''){ if($form_data_shared['window_view']['type']=='select_box' && intval($data_item['window_view'])!=0 && isset($form_data_shared['window_view'] ['select_data'][$data_item['window_view']])){ $rs.='<window-view>'.self::symbolsClear($form_data_shared['floor_covering']['select_data'][$data_item['floor_covering']]).'</window-view>'."\n"; }elseif($form_data_shared['window_view']['type']!='select_box' && $data_item['window_view']!=''){ $rs.='<window-view>'.self::symbolsClear($data_item['floor_covering']).'</window-view>'."\n"; }  
  5. Like
    abushyk получил репутацию от Dim42 в [HOWTO] Локальный grid_manager   
    Центральным местом, которое в 90% случаев обрабатывает запросы на извлечение нескольких записей-объявлений (всякого рода сетки-списки, в том числе и спецпредложениях в боковых колонках и забор данных для нанесения на карту), является файл /apps/system/lib/frontend/grid/grid_constructor.php - или Конструктор списка (КС).
    В нем много разного функционала, но самый часто востребованный лежит в двух функциях transformGridData - подготовка данных к выводу и prepareRequestParams - обработка параметров поиска.
    prepareRequestParams выполняет все операции связанные с тем, что бы превратить фильровочные переменные запроса, переданные в Конструктор списка, в части запроса к БД. Она имеет встроенную обработку некоторого числа параметров, но для расширения функционала иногда необходимо добавить свои. prepareRequestParams  НЕ обрабатывает параметры запроса прямо из строки браузера. Все параметры с веб-интерфейса перехватываются отдельной функцией, нормализуются и только тогда передаются в prepareRequestParams.
    transformGridData адаптирует результат выборки из БД к удобоваримому виду. Поскольку результатом выборки списка являются строки из БД, то именно эта функция трансформирует значения указанные ключем, например поля select_box и select_by_query  в текстовые значения. Эта функция так же умеет обрабатывать сама некоторые "стандартные" поля, например географические - country_id, region_id,... street_id, currency_id и все поля типа select_box. "Превращение" в текст остальные ссылочных полей необходимо реализовывать самому
    Как создать для шаблона локальный Grid_manager
    1. Переопределением метода в шаблоне (ручное) - устаревший
    В файле /template/frontend/имя_вашего_шаблона/main/main.php смотрим, есть ли функция __construct(). Если нет, то создаем ее внутри декларации class frontend_main extends SiteBill_Krascap {} в виде 
    public function __construct(){ parent::__construct(); require SITEBILL_DOCUMENT_ROOT.'/template/frontend/'.$this->getConfigValue('theme').'/main/grid/local_grid_constructor.php'; $this->_setGridConstructor(new Local_Grid_Constructor()); } 2. Переопределением метода в шаблоне (автоматическое) - устаревший
    В файле /settings.php.ini добавляем секцию описания локального Конструктора списков
    [GridConstructor] path='/main/grid/local_grid_constructor.php' name='Local_Grid_Constructor' Первая строка - имя секции
    вторая - путь к файлу локального Конструктора списка от корня шаблона
    третья - задекларированное имя класса локального Конструктора списка
    3. Настроечное переопределение - используйте, по возможности, именно этот вариант локализации
    Указываем в Настройки  - Общее галочку Использовать локальный Конструктор списка (classic_local_grid)
    Отличие последнего метода от остальных в том, что в нем имя класса конструктора и имя файла в котором он расположен должны быть соответственно Local_Grid_Constructor и template/frontend/имя_шаблона/grid/local_grid_constructor.php и никакими иначе.
    =============================================================================================
    Одним из этих способов мы указываем шаблону, что нужно использовать для построения списков наш измененный Конструктор списков. Но теперь нам необходимо создать его.
    Для этого нам нужно создать файл по адресу указанному в require_once для первого способа, в path для второго и в /template/frontend/имя_шаблона/grid/local_grid_constructor.php для третьего.
    Базовое наполнение этого файла будет иметь вид:
    class Local_Grid_Constructor extends Grid_Constructor { } Уже после этого локальный КС будет работать, но так как он пока пуст, то он просто, как транслятор, будет передавать заказы в стандартный КС. Для того, что бы добавить что-то свое, нам нужно внести в него изменения.
    1. Добавляем подхват текстового значения для поля типа select_by_query
    Поскольку это операция трансформации из ключевого значения в текстовое, то нам понадобится функция transformGridData . Так как остальные параметры нам нужны и мы просто хотим добавить своего, то мы делаем свою функцию с вызовом родительской
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info);/*используем "стандартный" вызов для выполнения привычных действий*/ /*тут мы можем сделать что-то свое с данными*/ return $data; /*возвращаемся в текущий процесс исполнения*/ } Итак у нас в объявлении есть поле station_id связывающее объект с некоторой станцией из внешней таблицы station в которой станции разложены по строкам вида station_id, name. Так как в данных объявления при выборке мы имеем только ключ станции, а хотим получить именно ее имя и штатный трансформатор за нас этого не делает, то мы проиводим следующее
    foreach($data as $k=>$d){ if ( $d['station_id'] > 0 ) { $data[$k]['station'] = $data_model->get_string_value_by_id('station', 'station_id', 'name', $d['station_id'], true); }else{ $data[$k]['station']=''; } } Либо
    $station_ids=array(); foreach($data as $k=>$d){ $station_ids[intval($d['station_id'])]=intval($d['station_id']); } if(!empty($station_ids)){ $DBC=DBC::getInstance(); $query='SELECT `station_id`, `name` FROM '.DB_PREFIX.'_station WHERE station_id IN ('.implode(',', $station_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $station_ids[$ar['station_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($station_ids[intval($d['station_id'])])){ $data[$k]['station']=$station_ids[intval($d['station_id'])]; }else{ $data[$k]['station']=''; } } первый способ короче, но второй на больших количествах записей более продуктивен и более удобен, если нужно получить сложные названия текстового значения, например сцепить с названием станции еще и какой-то другой признак из свойств самой станции.
    Для select_by_query второй вложенности, например если нужно получить имя застройщика, которое является свойством объекта ЖК, с которым связан объект, первый вариант уже не проходит. Т.е. использовать его конечно можно, но количество дополнительных действий сразу перекрывает сложность второго способа. Поэтому используем сразу второй.
    $complex_ids=array(); foreach($data as $k=>$d){ $complex_ids[intval($d['complex_id'])]=intval($d['complex_id']); } if(!empty($complex_ids)){ $DBC=DBC::getInstance(); $query='SELECT d.`name`, c.`complex_id` FROM '.DB_PREFIX.'_complex c LEFT JOIN '.DB_PREFIX.'_developer d USING (developer_id) WHERE complex_id IN ('.implode(',', $complex_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $complex_ids[$ar['complex_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($complex_ids[intval($d['complex_id'])])){ $data[$k]['developer']=$complex_ids[intval($d['complex_id'])]; }else{ $data[$k]['developer']=''; } } Очевидно, что принцип схожий и разница заключается только в мелочах вроде запроса на выборку связанного объекта. При чем, в зависимости от сложности желаемого к получению текстового значения будет меняться и сложность запроса, которая запросто может распасться на несколько.
    В итоге наш локальный КС будет выглядеть таким образом:
    <?php class Local_Grid_Constructor extends Grid_Constructor { public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info);/*используем "стандартный" вызов для выполнения привычных действий*/ /*тут мы можем сделать что-то свое с данными*/ $complex_ids=array(); foreach($data as $k=>$d){ $complex_ids[intval($d['complex_id'])]=intval($d['complex_id']); } if(!empty($complex_ids)){ $DBC=DBC::getInstance(); $query='SELECT `complex_id` FROM '.DB_PREFIX.'_complex WHERE complex_id IN ('.implode(',', $station_ids).')'; $query='SELECT d.`name`, c.`complex_id` FROM '.DB_PREFIX.'_complex c LEFT JOIN '.DB_PREFIX.'_developer d USING (developer_id) WHERE complex_id IN ('.implode(',', $complex_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $complex_ids[$ar['complex_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($complex_ids[intval($d['complex_id'])])){ $data[$k]['developer']=$station_ids[intval($d['complex_id'])]; }else{ $data[$k]['developer']=''; } } return $data; /*возвращаемся в текущий процесс исполнения*/ } } 2. Получаем дату в красивом формате
    Иногда нужно подготовить дату под вывод, что бы не мучаться с однотипными действиями в каждом шаблоне. Например подготовим дату добавления в виде "12 ноябра 2013 года".
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); $months=array( '1'=>'января', '2'=>'февраля', '3'=>'марта', '4'=>'апреля', '5'=>'мая', '6'=>'июня', '7'=>'июля', '8'=>'августа', '9'=>'сентября', '10'=>'октября', '11'=>'ноября', '12'=>'декабря', ); foreach($data as $k=>$d){ $month=date('n', $d['date_added']); $data[$k]['pretty_date']=date('j', $d['date_added']).' '.$months[date('n', $d['date_added'])].' '.$months[date('Y', $d['date_added'])]; } return $data; } и в поле pretty_date в шаблоне у нас будет искомая строка
    3. День добавления
    Подготовим дату добавления, что бы она показывала было ли добавлено объявление сегодня, вчера или в другой день.
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); $now=date('dmY'); $yesterday=date('dmY', time()-24*3600); foreach($data as $k=>$d){ if($now==date('dmY', strtotime($d['date_added']))){ $data[$k]['pretty_adddate']='сегодня'; }elseif($yesterday==date('dmY', strtotime($d['date_added']))){ $data[$k]['pretty_adddate']='вчера'; }else{ $data[$k]['pretty_adddate']=date('d.m.Y', strtotime($d['date_added'])); } } return $data; } Этот вариант можно скомбинировать с предыдущим.
    4. Форматирование адресной строки
    Форматируем строку адреса для списка вида "Нижний Тагил (Заводской), Лермонтова, 12" [Город (Район), Улица, Дом]
    protected function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); foreach($data as $k=>$d){ $addrline=array(); if($d['city']!=''){ if($d['district']!=''){ $addrline[]=$d['city'].' ('.$d['district'].')'; }else{ $addrline[]=$d['city']; } } if($d['street']!=''){ $addrline[]=$d['street']; if($d['number']!=''){ $addrline[]=$d['number']; } } if(!empty($addrline)){ $data[$k]['pretty_address']=implode(', ', $addrline); }else{ $data[$k]['pretty_address']=''; } } return $data; }  
  6. Like
    abushyk получил репутацию от XTRO в [HOWTO] Локальный grid_manager   
    Центральным местом, которое в 90% случаев обрабатывает запросы на извлечение нескольких записей-объявлений (всякого рода сетки-списки, в том числе и спецпредложениях в боковых колонках и забор данных для нанесения на карту), является файл /apps/system/lib/frontend/grid/grid_constructor.php - или Конструктор списка (КС).
    В нем много разного функционала, но самый часто востребованный лежит в двух функциях transformGridData - подготовка данных к выводу и prepareRequestParams - обработка параметров поиска.
    prepareRequestParams выполняет все операции связанные с тем, что бы превратить фильровочные переменные запроса, переданные в Конструктор списка, в части запроса к БД. Она имеет встроенную обработку некоторого числа параметров, но для расширения функционала иногда необходимо добавить свои. prepareRequestParams  НЕ обрабатывает параметры запроса прямо из строки браузера. Все параметры с веб-интерфейса перехватываются отдельной функцией, нормализуются и только тогда передаются в prepareRequestParams.
    transformGridData адаптирует результат выборки из БД к удобоваримому виду. Поскольку результатом выборки списка являются строки из БД, то именно эта функция трансформирует значения указанные ключем, например поля select_box и select_by_query  в текстовые значения. Эта функция так же умеет обрабатывать сама некоторые "стандартные" поля, например географические - country_id, region_id,... street_id, currency_id и все поля типа select_box. "Превращение" в текст остальные ссылочных полей необходимо реализовывать самому
    Как создать для шаблона локальный Grid_manager
    1. Переопределением метода в шаблоне (ручное) - устаревший
    В файле /template/frontend/имя_вашего_шаблона/main/main.php смотрим, есть ли функция __construct(). Если нет, то создаем ее внутри декларации class frontend_main extends SiteBill_Krascap {} в виде 
    public function __construct(){ parent::__construct(); require SITEBILL_DOCUMENT_ROOT.'/template/frontend/'.$this->getConfigValue('theme').'/main/grid/local_grid_constructor.php'; $this->_setGridConstructor(new Local_Grid_Constructor()); } 2. Переопределением метода в шаблоне (автоматическое) - устаревший
    В файле /settings.php.ini добавляем секцию описания локального Конструктора списков
    [GridConstructor] path='/main/grid/local_grid_constructor.php' name='Local_Grid_Constructor' Первая строка - имя секции
    вторая - путь к файлу локального Конструктора списка от корня шаблона
    третья - задекларированное имя класса локального Конструктора списка
    3. Настроечное переопределение - используйте, по возможности, именно этот вариант локализации
    Указываем в Настройки  - Общее галочку Использовать локальный Конструктор списка (classic_local_grid)
    Отличие последнего метода от остальных в том, что в нем имя класса конструктора и имя файла в котором он расположен должны быть соответственно Local_Grid_Constructor и template/frontend/имя_шаблона/grid/local_grid_constructor.php и никакими иначе.
    =============================================================================================
    Одним из этих способов мы указываем шаблону, что нужно использовать для построения списков наш измененный Конструктор списков. Но теперь нам необходимо создать его.
    Для этого нам нужно создать файл по адресу указанному в require_once для первого способа, в path для второго и в /template/frontend/имя_шаблона/grid/local_grid_constructor.php для третьего.
    Базовое наполнение этого файла будет иметь вид:
    class Local_Grid_Constructor extends Grid_Constructor { } Уже после этого локальный КС будет работать, но так как он пока пуст, то он просто, как транслятор, будет передавать заказы в стандартный КС. Для того, что бы добавить что-то свое, нам нужно внести в него изменения.
    1. Добавляем подхват текстового значения для поля типа select_by_query
    Поскольку это операция трансформации из ключевого значения в текстовое, то нам понадобится функция transformGridData . Так как остальные параметры нам нужны и мы просто хотим добавить своего, то мы делаем свою функцию с вызовом родительской
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info);/*используем "стандартный" вызов для выполнения привычных действий*/ /*тут мы можем сделать что-то свое с данными*/ return $data; /*возвращаемся в текущий процесс исполнения*/ } Итак у нас в объявлении есть поле station_id связывающее объект с некоторой станцией из внешней таблицы station в которой станции разложены по строкам вида station_id, name. Так как в данных объявления при выборке мы имеем только ключ станции, а хотим получить именно ее имя и штатный трансформатор за нас этого не делает, то мы проиводим следующее
    foreach($data as $k=>$d){ if ( $d['station_id'] > 0 ) { $data[$k]['station'] = $data_model->get_string_value_by_id('station', 'station_id', 'name', $d['station_id'], true); }else{ $data[$k]['station']=''; } } Либо
    $station_ids=array(); foreach($data as $k=>$d){ $station_ids[intval($d['station_id'])]=intval($d['station_id']); } if(!empty($station_ids)){ $DBC=DBC::getInstance(); $query='SELECT `station_id`, `name` FROM '.DB_PREFIX.'_station WHERE station_id IN ('.implode(',', $station_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $station_ids[$ar['station_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($station_ids[intval($d['station_id'])])){ $data[$k]['station']=$station_ids[intval($d['station_id'])]; }else{ $data[$k]['station']=''; } } первый способ короче, но второй на больших количествах записей более продуктивен и более удобен, если нужно получить сложные названия текстового значения, например сцепить с названием станции еще и какой-то другой признак из свойств самой станции.
    Для select_by_query второй вложенности, например если нужно получить имя застройщика, которое является свойством объекта ЖК, с которым связан объект, первый вариант уже не проходит. Т.е. использовать его конечно можно, но количество дополнительных действий сразу перекрывает сложность второго способа. Поэтому используем сразу второй.
    $complex_ids=array(); foreach($data as $k=>$d){ $complex_ids[intval($d['complex_id'])]=intval($d['complex_id']); } if(!empty($complex_ids)){ $DBC=DBC::getInstance(); $query='SELECT d.`name`, c.`complex_id` FROM '.DB_PREFIX.'_complex c LEFT JOIN '.DB_PREFIX.'_developer d USING (developer_id) WHERE complex_id IN ('.implode(',', $complex_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $complex_ids[$ar['complex_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($complex_ids[intval($d['complex_id'])])){ $data[$k]['developer']=$complex_ids[intval($d['complex_id'])]; }else{ $data[$k]['developer']=''; } } Очевидно, что принцип схожий и разница заключается только в мелочах вроде запроса на выборку связанного объекта. При чем, в зависимости от сложности желаемого к получению текстового значения будет меняться и сложность запроса, которая запросто может распасться на несколько.
    В итоге наш локальный КС будет выглядеть таким образом:
    <?php class Local_Grid_Constructor extends Grid_Constructor { public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info);/*используем "стандартный" вызов для выполнения привычных действий*/ /*тут мы можем сделать что-то свое с данными*/ $complex_ids=array(); foreach($data as $k=>$d){ $complex_ids[intval($d['complex_id'])]=intval($d['complex_id']); } if(!empty($complex_ids)){ $DBC=DBC::getInstance(); $query='SELECT `complex_id` FROM '.DB_PREFIX.'_complex WHERE complex_id IN ('.implode(',', $station_ids).')'; $query='SELECT d.`name`, c.`complex_id` FROM '.DB_PREFIX.'_complex c LEFT JOIN '.DB_PREFIX.'_developer d USING (developer_id) WHERE complex_id IN ('.implode(',', $complex_ids).')'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $complex_ids[$ar['complex_id']]=$ar['name']; } } } foreach($data as $k=>$d){ if(isset($complex_ids[intval($d['complex_id'])])){ $data[$k]['developer']=$station_ids[intval($d['complex_id'])]; }else{ $data[$k]['developer']=''; } } return $data; /*возвращаемся в текущий процесс исполнения*/ } } 2. Получаем дату в красивом формате
    Иногда нужно подготовить дату под вывод, что бы не мучаться с однотипными действиями в каждом шаблоне. Например подготовим дату добавления в виде "12 ноябра 2013 года".
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); $months=array( '1'=>'января', '2'=>'февраля', '3'=>'марта', '4'=>'апреля', '5'=>'мая', '6'=>'июня', '7'=>'июля', '8'=>'августа', '9'=>'сентября', '10'=>'октября', '11'=>'ноября', '12'=>'декабря', ); foreach($data as $k=>$d){ $month=date('n', $d['date_added']); $data[$k]['pretty_date']=date('j', $d['date_added']).' '.$months[date('n', $d['date_added'])].' '.$months[date('Y', $d['date_added'])]; } return $data; } и в поле pretty_date в шаблоне у нас будет искомая строка
    3. День добавления
    Подготовим дату добавления, что бы она показывала было ли добавлено объявление сегодня, вчера или в другой день.
    public function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); $now=date('dmY'); $yesterday=date('dmY', time()-24*3600); foreach($data as $k=>$d){ if($now==date('dmY', strtotime($d['date_added']))){ $data[$k]['pretty_adddate']='сегодня'; }elseif($yesterday==date('dmY', strtotime($d['date_added']))){ $data[$k]['pretty_adddate']='вчера'; }else{ $data[$k]['pretty_adddate']=date('d.m.Y', strtotime($d['date_added'])); } } return $data; } Этот вариант можно скомбинировать с предыдущим.
    4. Форматирование адресной строки
    Форматируем строку адреса для списка вида "Нижний Тагил (Заводской), Лермонтова, 12" [Город (Район), Улица, Дом]
    protected function transformGridData($ra, $_collect_user_info=false){ $data=parent::transformGridData($ra, $_collect_user_info); foreach($data as $k=>$d){ $addrline=array(); if($d['city']!=''){ if($d['district']!=''){ $addrline[]=$d['city'].' ('.$d['district'].')'; }else{ $addrline[]=$d['city']; } } if($d['street']!=''){ $addrline[]=$d['street']; if($d['number']!=''){ $addrline[]=$d['number']; } } if(!empty($addrline)){ $data[$k]['pretty_address']=implode(', ', $addrline); }else{ $data[$k]['pretty_address']=''; } } return $data; }  
  7. Like
    abushyk получил репутацию от Helenblondi в Статусы объявлений   
    В принципе подобие статуса Продано\Архивировано есть. Это чекбокс с именем archived установка которого переводит объявку в некоторое "полудохлое" состояние, когда она не светится в поиске с формы поиска, но открывается по прямой ссылке. Но эта опция получилась заумной и требующей включения еще пары галочек (привет галочкам "Использовать предудаление" и "Архивированные объявления полностью не доступны") и сильно слилась с понятием "удаления в архив" и вообще процессом удаления. Так что использовать ее пока сложно, тем более, что такие объявки еще и из списка в админке вылетают из общего и для ЛК перевод в это состояние завязан на кнопке удаления. Поэтому использовать ее сейчас по требуемому назначению я бы не рекомендовал. Скорее мы запилим некую лайт-версию такой же галочки с предустановленным поведением.
    ПС. Наделать статусов дело не хитрое. Все упирается в а) обилие желаемых статусов (опросить пять форумчан и насобирается с два десятка разных "критически нужных" статусов))) )  б) трактовки смысла одного и того же статуса и его влияния на окружающую среду кода.
  8. Like
    abushyk получил репутацию от metrpro в [Песочница] Пользовательские сущности и Связанные элементы   
    1. Предистория
     
    Допустим мы имеем базовый сайт на сайтбилле. У нас есть стандартная модель квартиры-недвижимости со всякими Цена, Площадь и прочими свойствами по вкусу. И вот, в один прекрасный момент, мы решили заняться торговлей квартирами в новостройках. А новостройки эти у нас зачастую представлены не отдельными зданиями, а целыми комплексами зданий, которые в свою очередь разбиты на секции.
     
    2. Анализ.
     
    Сначала разберемся со структурой. Самый простой вариант - мы решили еализовывать каждую квартиру в виде отдельного объекта. Например, если в ЖК "Элитный" у нас есть корпус А, а в нем секция I и в этой секции, грубо говоря, 15 квартир одной планировки, но некоторые на разных этажах, мы будем считать, что каждая квартира, даже одинаковой планировки - является одним объектом. Иными словами, мы не делаем группировок по типам, а ведем каждую квартиру отдельно. Это дает нам некоторую гибкость, так как квартиры на крайних этажах могут иметь меньшую цену в отличии от одноплановых с ними, на остальных этажах. Так же, из плюсов то, что мы можем задать какие-то особенности поквартирно, даже не смотря на то, что они одноплановые. Особенно это касается, когда квартиры продаются не в сыром виде, а меблированные или с финишной отделкой. Либо учесть иные особенности каждой квартиры.
     
    Из минусов такого подхода то, что если секция у нас 9-ти этажная с 4 квартирами на этаж, то на секцию получается 36 объектов. И дальше в геометрической прогрессии в зависимости от количества секций в корпусе и корпусов в ЖК.
     
    Соответственно, логично предположить, что кроме обычных для недвижимости параметров (цена, площадь, этаж,и т.д.) нам придется снабдить модель недвижимости дополнительными параметрами, устанавливающими ее привязку к конкретному положению в разрезе ЖК - конкретный ЖК, корпус ЖК, секция корпуса ЖК. И так же очевидно, что при заполнении формы эти параметры должны бы быть связаны цепочкой, как то при выборе отдельного ЖК, мы должны получить под выбор список корпусов только этого ЖК, что бы не рыскать в длиннющем списке всех корпусов. Аналогино и с секциями.
     
    3. Инструментарий.
     
    Для реализации нам понадобятся свежие приложения system, admin, table, customentity. Привлекать готовые приложения типа "Жилые комплексы" мы не будем.
     
    Из настроек нам будет необходимо включить параметр Настройки - Дополнительно - Off system Ajax. Данная опция выключает автоматические связки между зависимыми элементами и предоставляет нам полный контроль над определением своих зависимостей.
     
    Из почитать - http://wiki.sitebill.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D1%8B
     
    4. Подготовка дополнительных сущностей.
     
    Если мы должны иметь возможность выбрать корпус, ЖК и секцию, значит у нас где-то должны быть списки этих значений. В Сайтбилле, для организации списков значений существует два типа полей - select_box и selectbox_by_query.
     
    Первый нам не подходит, так как не поддерживает организацию наследия. Т.е. штатными средствами этого элемента мы можем задать набор его вариантов значений, но не можем указать какие-то связующие ключи с другим элементом.
     
    Второй, поскольку хранится в БД в виде отдельной таблицы, вполне на это способен. Но для его использования необходима соответствующая таблица в БД. В нашем случае таблиц будет три - таблица ЖК, таблица корпусов и секций корпусов. Что бы избавить себя от рутинной работы по наполнению этих данных через phpMyAdmin создадим соответствующие таблицы в Редакторе форм.
     
    4.1. Жилые комплексы.
     
    Для ЖК - это таблица czhilkom с полями czhilcom_id (primary_key) и name (safe_string).

    Создав таблицу и наполнив ее элементами, нажимаем кнопку Создать таблицу.

    Теперь таблица ЖК существует физически в БД.
    Надо наполнить ее какими-то жилыми комплексами.
    Для того, что бы получить доступ к работе с этой сущность через стандартную админку, воспользуемся приложением Пользовательские сущности. Для начала проверим, что приложение установлено. Для этого в админке переходим по адресу 
    /admin/index.php?action=customentity&do=install
     
    При переходе по нему, в случае отсутствия необходимых таблиц для работы приложения, они будут созданы.
    После этого возвращаемся в Редактор форм и в заголовке таблицы czhilkom ищем кнопку со завездочкой

    Эта кнопка отвечает за создание мини-обработчика для сущности, у которой нет штатного обработчика (в виде встроенного модуля или стандартного\стороннего приложения). NB. Попытка создать этой кнопкой обработчик для встроенных сущностей, как Город, Район или для тех у которых есть приложения - Баннеры, Новости - ни к чему не приведет.
     
    После нажатия кнопки Создания обработчика мы увидим следующее окно

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

    Если перейти по предложенной ссылке, вы получите минималистический инструмент для управления вашими ЖК где вы можете добавить ЖК в список, изменить существующий или удалить ненужный. Приложение не следит за целостностью, т.е. если вы удаляете ЖК, то об удалении соответствующих зависимых корпусов и секций вам так же придется позаботиться самому.
     
    Не надейтесь на возможность реализации таким способом каких-то "творческих вывихов" - это исключительно инструмент для обеспечения удобства. Для полноценной работы с такими сущностями, как разделение их по пользователям с возможностью редактирования последними, организация страницы, например конкретного ЖК, шаблонизация необходимо создавать полноценное приложение.
     
    Для наших целей добавим два ЖК - Элитный и Морской с помощью кнопки Добавить запись
    Процесс, как вы можете заметить, вполне привычный и не должен вызвать трудностей
     
    4.1. Корпуса.
     
    Создание таблицы корпусов абсолютно ничем не отличается от создания таблицы ЖК кроме того, что у корпусов есть зависимость от ЖК. Например ЖК Элитный имеет два корпуса - Корпус А и Корпус Б. Тогда модель корпуса (ckorps) будет состоять из полей

    Поле czhilcom_id является обычным полем селектбокса подбирающим данныеиз внешней таблицы, в данном случае из таблицы czhilcom
    Простыня под спойлером
     
    Дальше все по алгоритму - создали таблицу в Редакторе форм, наполнили полями, создали физическую таблицу, зарегистрировали обработчик. Из Пользовательских переходим в Корпуса  добавляем

    Названия сущностей рекомендую давать расширенные - с включением родительского описания. Так как обработчик весьма прост, то особых способов отличить Корпус А от ЖК Элитный и Корпус А от ЖК Морской у вас не будет.
     
    В результате мы получаем нечто похожее на 

  9. Like
    abushyk получил репутацию от metrpro в Cтраница с объектами агента /userХХ.html   
    $query='SELECT COUNT( d.id ) AS _cnt, u.group_id, u.city_id, u.user_id, u.fio, u.profilevk, u.profileok, u.profilefb, u.groupvk, u.groupok, u.groupfb, u.phone, u.imgfile, u.mobile, u.email, u.site, u.skype, u.yac1, u.yac2, u.ofadres, u.vibernum, u.fullinfo, g.name AS group_name, ci.name AS city_name FROM `'.DB_PREFIX.'_data` d LEFT JOIN '.DB_PREFIX.'_user u USING ( user_id ) LEFT JOIN '.DB_PREFIX.'_group g USING ( group_id ) LEFT JOIN `'.DB_PREFIX.'_city` ci ON u.city_id=ci.city_id WHERE u.group_id<>4 AND d.user_id=?'; В city_name будет текстовое имя города.
    Это если в лоб. Но такой запрос конечно уже лучше делить на два более простых. Или его результат сохранять на какой-то срок, что бы он не пересобирал данные каждую секунду.
  10. Like
    abushyk получил репутацию от metrpro в Cтраница с объектами агента /userХХ.html   
    1. нет любого случая - есть только один вариант city_name, ну или city_id для числа.
    2. Город не сохраняется. Вот отсюда и проблема. Я задавал город юзеру, но после сохранения он все равно сброшен в ноль.
    По самому элементу в модели юзера косяков быть не должно. В редакторе она выглядит "як книжка пише". Проверьте таблицу re_user через пхпмайадмин, что творится с полем city_id. Является ли оно просто INT-типа, без всяких ключей на нем. Существует ли оно вообще. Не жалуется ли эта таблица на поломки и не просит ли починить ее. Начните с этого.
  11. Like
    abushyk получил репутацию от metrpro в Cтраница с объектами агента /userХХ.html   
    Все. Отбой. Смотрим поле Запрос для элемента выбора города в модели юзера
    select re_city.name from re_city order by name человеческим языком здесь значится, что "используй в запросе на выборку списка городов только значения из колонки name сортированные по полю name". Все бы хорошо, но разом с этим из выборки были исключены ключи, которые подставляются в аттрибут value для опций селектбокса списка городов и которые используются для создания связи между юзером и городом.
    Так что верный запрос должен был выглядеть или как 
    select * from re_city order by name или как
    select city_id, name from re_city order by name Первый безопаснее, так как хз что может быть понадобится еще кроме названия и ключа в будущем.
    ПС. Поэтому и города не прописывались на юзера, так как не было идешки и, естественно, не выводились даже по последнему запросу. Проставляйте и наслаждайтесь. Для пробы на АН "Эксклюзив" я выставил.
  12. Like
    abushyk получил репутацию от Smoke в Проблема при проверке платежа на существование   
    если номер платежа верный, но спотык точно на $stmt тогда все упирается в status и его значение.
    Так же можно убрать неиспользуемую переменную в запросе 
    $payment в строке
    $stmt=$DBC->query($query, array($bill_id, $payment)); ---->
    $stmt=$DBC->query($query, array($bill_id));
  13. Like
    abushyk получил репутацию от Александр Лубянский в Создание приватных полей   
    замените на
     
    {if is_array($data.documents.value) && count($data.documents.value) > 0} {foreach name=j from=$data.documents.value item=document_item} <a target="_blank" href="{$estate_folder}/img/mediadocs/{$document_item.normal}">{if $document_item.title != ''}{$document_item.title}{else}{$document_item.normal}{/if}</a><br/> {/foreach} {/if} разница только в первой строке.
  14. Like
    abushyk получил репутацию от Александр Лубянский в Модуль статьи для сайта   
    И еще после 
    $arts=$AA->getArticlesList($params); сделайте var_dump($arts);
    что бы убедиться, что статьи выбрались и не работает только вывод.
  15. Like
    abushyk получил репутацию от Александр Лубянский в Модуль статьи для сайта   
    В контроллере шаблона main.php после вызова приложений
    if(!$has_result){ $apps_processor = new Apps_Processor(); $apps_processor->run_frontend(); if ( count($apps_processor->get_executed_apps()) > 0 ) { $work_subcontroller='apps'; $has_result=true; } } добавляем запрос на выборку
    $AA=new articles_site(); $params=array(); $arts=$AA->getArticlesList($params); $this->template->assert('main_page_articles', $arts['articles']); В результате вы получите до 10 последних статей. Что бы изменить это количество
    $params=array(); нужно заменить на
    $params=array('per_page'=>5); Теперь в шаблоне у вас будет переменная {$main_page_articles} которая будет содержать набор статей в виде массива моделей. Дальше прокручиваем ее в цикле и выводим аналогично как это сделано в /apps/articles/site/template/list.tpl
    NB. В текущей версии функция getArticlesList недоступна извне. Поэтому в файле /apps/articles/admin/admin.php необходимо изменить
    protected function getArticlesList на public function getArticlesList
    Со следующей версии это изменение будет учтено.
  16. Like
    abushyk получил репутацию от kkkv39 в Запрет добавлять похожие объявления.   
    В принципе можно включить любое текстовое поле safe_string, select_... Проверяется по полному совпадению. Проверять по частичному я не вижу смысла, так как это только человек сможет достоверно определить является ли два описания реально схожими или нет - т.е. не нужно пытаться отнять хлеб у человека-модератора.
     
    Но в целом проверять похожесть по описанию - плохая идея. Одна запятая и все, уже не похоже. Оптимально проаерять только по однозначным данным.
  17. Like
    abushyk получил репутацию от bogdanoff в Скачать кэшированный файл выгрузки   
    1. Кешированный файл сбрасывается в корень сайта в www или htdocs.
    2. Формально любой десктопный редактор поддерживает, лишь бы системе хватило оперативки для его загрузки в редактор. А реально тут зависит от редактора. я использую для таких толстых - Notepad++ Он конечно скрипит, но открывает. Хотя поиск по таким файлам, даже если редактор его открыл, конечно уже становится проблематичным.
  18. Like
    abushyk получил репутацию от Pavel_S в Организовать на своём сайте выгрузку со сторонних сайтов   
    Заморачиваться стоит если:
    1. реально получить профит - арендные платежи, процент с реализаций, еще какие-то меркантильные бонусы. Ну это наверное самое главное)
    2. вы уже лидер и вам просто нужно расширить базу предложений, что бы еще более увеличился клиентооборот
    3. вам по приколу и вы хотите понять каково это управляться и упорядочивать несколькими тысячами чужих объяв заливаемых из разных источников, в том числе и с офигительным дублированием и с самой разнообразной географией. в общем если хочется перчинки))
    4. если вы не ограничитель только простой заливкой к себе, а начнете предлагать и разрабатывать какие-то программы как поощряющие так и ограничивающие для заливальщиков.
     
    Заморачиваться не стоит если:
    1. вы на начальной стадии раскрутки. Выгрузчики надают вам неуникальных текстовых описаний, которые они параллельно выдают еще на другие коллекторы и которые, вполне часто, сами получают со сторонних коллекторов или других людей, которые сами копипастят одно и то же описание всюду. грубо говоря если вы не закроете все объявки или хотя бы их описания от индекса, то кубок копипастера скорее вас найдет.
    2. если ваш сервер слабоват. парсинг ресурсоемкий. хранение графматериала требует физдиска. база тоже. не дай бог еще клиенты повалят)))
    3. если у вас нет времени ежедневно ковыряться в этом шлаке, который будут вам сливать. два дня без контроля и эти авгиевы конюшни уже будет не разгрести.
  19. Like
    abushyk получил репутацию от DoobBY в Переключатель валют.   
    Делаем userfriendly-переключатель отображения валют.
     
    Исходным материалом будет http://www.etown.ru/s/topic/1742-отображение-валют/?p=18682.
     
    1. Что нам понадобится.
     - заготовки из указанной статьи
     - jquery библиотека https://github.com/carhartl/jquery-cookie. Без нее можно обойтись, но с ней быстрее
     
    2. Модернизируем код контроллера (main.php)
    В контроллере мы готовили массив курсов валют. Изменим его немного
    if(!isset($_SESSION['site_cache']['courses'])){ $DBC=DBC::getInstance(); $query='SELECT * FROM '.DB_PREFIX.'_currency'; $stmt=$DBC->query($query); if($stmt){ while($ar=$DBC->fetch($stmt)){ $ar['code_id']=strtolower(trim($ar['code'])); $courses[$ar['currency_id']]=$ar; } } $_SESSION['site_cache']['courses']=$courses;}$this->template->assign('_courses', $_SESSION['site_cache']['courses']);if(isset($_COOKIE['current_view_currency']) && $_COOKIE['current_view_currency']!=''){ $this->template->assign('_current_view_currency', $_COOKIE['current_view_currency']);}else{ setcookie('current_view_currency', 'eur'); $this->template->assign('_current_view_currency', 'eur');} В чем отличие? В данные курсов мы добавили переменную code_id - это приведенный к нижнему регистру код валюты, что бы мы этим не занимались в шаблоне.
    Так же мы проверяем куки на наличие значения current_view_currency и если его нет, то заполняем его "eur" либо другой дефолтной валютой (кодом валюты приведенным к нижнему регистру). И отправляем эту переменную в шаблон.
     
    Вот и все в контроллере. Идем в шаблон.
     
    3. Модернизация шаблона (realty_grid.tpl - либо какой-то из его подчиненных типа табличного или плиточного видов)
     
    В этом шаблоне у нас должно быть два момента:
    а) некий чекер с именами\кодами валют, куда бы мы кликали, что бы выбрать валюту.
    б) некий блок цен с ценами в разных валютах на строке или блоке объявления.
     
    Начнем с чекера-переключателя. Поставим его, в области над списком.
    {foreach from=$_courses item=_course} <div class="show_valute{if $_course.code_id==$_current_view_currency} active{/if}" data-codeid="{$_course.code_id}">{$_course.code}</div>{/foreach} тут не сложно. прокручиваем массив валют из контроллера мы выводим их в виде
    <div class="show_valute" data-codeid="rur">RUR</div><div class="show_valute active" data-codeid="usd">USD</div><div class="show_valute" data-codeid="eur">EUR</div> Класс show_valute указывает управляющую кнопку, а active - активное состояние переключателя.
     
    Код вывода разновалютных цен в блоке объявления
     
    <div class="valutes">{foreach from=$_courses item=_course} <div class="course_price {$_course.code_id}" style="{if $_course.code_id!=$_current_view_currency}display: none;{/if}">{$_course.code}: {(($grid_items[i].price*$_courses[$grid_items[i].currency_id].course)/($_course.course))|number_format:0:",":" "}</div>{/foreach}</div> Главное отличие - мы выводим цены в общий блок с классом valutes и, кроме этого, каждую цену внутри своего блока с класами course_price и тем кодом валюты(названием кода валюты приведенным к нижнему регистру). Вместе с этим мы проверяем текущую "отображаемую" валюту, которую ищем в куках и те блок, которые соответствуют другим валютам обозначаем стилем display: none; иными словами прячем.
     
    В результате у нас в блоках объявлений всегда будет показана только одна цена в той валюте, которая лежала в куках, либо дефолтной, если ее там не было.
    А общий виду будет такой
    <div class="valutes"> <div class="course_price rur" style="display: none;">RUR: 13 774 091</div> <div class="course_price usd" style="">USD: 568 181</div> <div class="course_price eur" style="display: none;">EUR: 454 545</div></div> 3. Добавляем красоту и интерактив.
    Включаем библиотеку jquery.cookie.js
     
    У меня она лежит в /third/jquery.cookie/ поэтому в шаблоне сетки я ее подключаю как 
    <script type="text/javascript" src="{$estate_folder}/third/jquery.cookie/jquery.cookie.js"></script> На стилях не останавливаюсь.
    {literal}<style>.show_valute.active {font-weight: bold;cursor: auto;}.show_valute {cursor: pointer;}</style>{/literal} А вот и сам скрипт
    {literal}<script>$(document).ready(function(){$('.show_valute').click(function(){var _this=$(this);var codeid=_this.data('codeid');_this.addClass('active').siblings().removeClass('active');$('.valutes .course_price').hide();$('.valutes .'+codeid).fadeIn();$.cookie('current_view_currency', codeid);});});</script>{/literal} Кратко: кликая по элементу с классом show_valute мы берем у этого элемента значение из аттрибута data-codeid, запоминаем его, прячем все разновалютные курсы и показываем только те блоки, которые имеют класс аналогичный запрошенному коду валюты. И пакуем этот код в куки, что бы при рефреше страницы у нас уже показались нужные валюты.
  20. Like
    abushyk получил репутацию от Realtor в Приложение Баннер   
    Фильтры - это дополнительная фильтрация. Сейчас поддерживает только одно значение hot=1 - фильтрацию по полю hot и значению в нем 1.
    Видимых элементов - это значение которое относится к типу вывода в виде слайдеров и указывает сколько видмых элементов будет показываться в поле показа слайдера
    Формат подписи - форматированная строка по принципу как указывается для заголовка объекта в карточке {banner_title} = {price}   Все что вне фигурных скобок, останется на месте, а все что в них будет предпринята попытка заменить текстовым значением из соотв. поля модели.
  21. Like
    abushyk получил репутацию от Xlebosolniy в Обязательное поле   
    Сделать ключи числовыми.
    {0~~Выбрать} {1~~Бетонные блоки} {2~~Дерево} {3~~Кирпич} {4~~Кирпич монолит} {5~~Монолит} {6~~Панель} {7~~Шлакоблоки} {8~~Другое} Для выборных элементов ключ со значением 0 всегда расценивается как невыбранное значение.
  22. Like
    abushyk получил репутацию от Chernetskiy в Дополнительное описание в data и realty_view.tpl   
    <div class="noverview-full"> {if $data.text.value != ''} <p align="justify">{$data.text.value}</p> {if $data.extended.value != ''} <!-- вот важное условие, которое выведет горизонталку только еcли есть расширенный текст --> <hr> <p align="justify">{$data.extended.value}</p> {/if} {/if}</div> А если нет расширенного, то и горизонтальная не выведется.
  23. Like
    abushyk получил репутацию от FD в Шаблон realia - пожалуйста, помогите с меню категорий [Решено]   
    Можете показать полность строку с добавленным вами пунктом? Что-то вроде этого
    $menues=array( array('id'=>0,'title'=>'Главная','position'=>'behind'), array('id'=>1000,'title'=>'Отзывы','position'=>'behind','href'=>'review'), array('id'=>215,'title'=>'Полезно','position'=>'after'), array('id'=>22,'title'=>'Иногородняя недвижимость','position'=>'after') );  
  24. Like
    abushyk получил репутацию от doma в Выгрузка Yandex.Realty   
    Если брать смый общий случай, то я иногда делаю в шаблоне вот так: {if $some_phone_number != '' && $some_phone_number|strlen==12}{$some_phone_number|regex_replace:'/(\d{3,3})(\d{2,2})(\d{3,3})(\d{2,2})(\d{2,2})$/':'+${1} (${2}) ${3}-${4}-${5}'}{/if} Самая примитивная регулярка которая раздирает исходных набор цифр на куски и форматирует из кусочков нужное отображение.
    Для mobilephone, которые однотипны и имеют равную длину и числовую составляющую, работает на ура.
     
    Для прочих номеров возможно больше вариантов из-за необходимости очистки исходного номера от мусора и разной длины номеров из-за свободной формы записи.
  25. Like
    abushyk получил репутацию от yurijp в отсутствует счетчик просмотров квартир   
    Просто тег label по стилям идет как блочный элемент, который занимает всю ширину и остальное - количество просмотров в данном случае, сталкивает в следующую строку. Нужно либо label убрать, либо для этого конкретного элемента присвоить стиль, сделающий его не блочным. И обертку <li></li> нужно убрать - там у вас нет обрамляющего <ul> поэтому и li лишний.