Показаны сообщения с ярлыком PHP. Показать все сообщения
Показаны сообщения с ярлыком PHP. Показать все сообщения

среда, 31 января 2018 г.

PHPExcel 1.8 - getAllBorders bug - не выделяются границы

В общем дело происходило вот так

$Sheet->getStyle('A5:E9')->getBorders()
->getAllBorders()
->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);

Но я перенес свой проектик с php5.4 на 7.1 и у меня очень много ошибок начало вылазить, не долго думая, решил обновить PHPExcel 1.7.6 -> 1.8, после обновления, у меня перестали применяться стили к границам ячеек.

Ну я залез в файл PHPExcel/Style/Border.php
и на 141 строке нашел функцию getStyleArray

public function getStyleArray($array)
    {
        switch ($this->parentPropertyName) {
            case 'allBorders':
            case 'bottom':
            case 'diagonal':
            case 'horizontal':
            case 'inside':
            case 'left':
            case 'outline':
            case 'right':
            case 'top':
            case 'vertical':
                $key = strtolower('vertical');
                break;
        }
        return $this->parent->getStyleArray(array($key => $array));
    }


Смешно, да?
При любом положении bottom, diagonal... у нас будет vertical.

Теперь обратимся к более ранней версии этой функции (1.7.6)

public function getStyleArray($array)
    {
        switch ($this->_parentPropertyName) {
        case '_allBorders':
            $key = 'allborders';
            break;

        case '_bottom':
            $key = 'bottom';
            break;

        case '_diagonal':
            $key = 'diagonal';
            break;

        case '_horizontal':
            $key = 'horizontal';
            break;

        case '_inside':
            $key = 'inside';
            break;

        case '_left':
            $key = 'left';
            break;

        case '_outline':
            $key = 'outline';
            break;

        case '_right':
            $key = 'right';
            break;

        case '_top':
            $key = 'top';
            break;

        case '_vertical':
            $key = 'vertical';
            break;
        }
        return $this->_parent->getStyleArray(array($key => $array));
    }



Т.е. в старой версии к нам приходили значения с префиксом _, а на выходе без префикса, в новой версии библиотеки перепилили всё и входные стали без префикса, но разработчики немного были невнимательными и хотели сказать что-то вроде такого:
public function getStyleArray($array)
    {
        switch ($this->parentPropertyName) {
            case 'allBorders':
            case 'bottom':
            case 'diagonal':
            case 'horizontal':
            case 'inside':
            case 'left':
            case 'outline':
            case 'right':
            case 'top':
            case 'vertical':
                $key = strtolower(
$this->parentPropertyName);
                break;
        }
        return $this->parent->getStyleArray(array($key => $array));
    }




После этого всё заработало, ура!!! Сейчас попробуем отправить разработчикам патч, хоть проект и закопали, но кому-то он еще нужен, у кого-то используется и пусть он живет за счет тех, кто это вообще использует.

среда, 12 февраля 2014 г.

PHPExel default codepage кодировка по умолчанию

При чтении файла отображались иероглифы, оказалось что файл экселя был кривым и кодировка в заголовке не была указана, по умолчанию PHPExel включает кодировку cp1252, тогда как в православной виндовой кириллице cp1251.

Открываем файл Reader/Exel5.php
и находим по слову 1252
Исправляем параметр на CP1251 и вуаля, бракованый XLS (генерируемый непонятной складской программой у поставщиков).


Далее я столкнулся еще с одной проблемой - когда определенная кодировка оказывается неподдерживаемой, хотя на деле cp1251.

Файл PHPExcel/Shared/CodePage.php, примерно после 89 строки нужно добавить выделенную красным цветом строку:

            case 32769:    throw new Exception('Code page 32769 not supported.');
                                            break;    //    ANSI Latin I (BIFF2-BIFF3)
            case 65001:    return 'UTF-8';        break;    //    Unicode (UTF-8)
            default: return 'CP1251';
        }

        throw new Exception('Unknown codepage: ' . $codePage);

пятница, 29 ноября 2013 г.

WebAsyst ShopScript подкатегории в расширеном поиске

В файле /published/SC/html/scripts/modules/test/_methods/category_search_result.php
дописываем
 $smarty->assign( 'subcategories_to_be_shown', catGetSubCategoriesSingleLayer($categoryID));

конец файла примерно такой
                if ( CONF_PRODUCT_SORT == '1' )_sortSetting( $smarty, set_query() );
                //calculate a path to the category
                 $smarty->assign( 'subcategories_to_be_shown', catGetSubCategoriesSingleLayer($categoryID));

                $smarty->assign( 'product_category_path', catCalculatePathToCategory($categoryID) );
                $smarty->assign( 'search_with_change_category_ability', 1 );
                $smarty->assign( 'catalog_navigator', $navigatorHtml );
                $smarty->assign( 'products_to_show', $products);
}
$smarty->assign( 'main_content_template', 'category_search.html');
?>




и всё!

понедельник, 19 августа 2013 г.

Модификация всех ссылок на PHP (вырезание ссылок из HTML на PHP)

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


 $pattern = '(<a.*?href=[\'"]{0,1}([^"\'\s]+)[^>]*>(.*?)<\/a>)sim';

//открытие всех ссылок в новом окне и отключение индексации
$htm = preg_replace($pattern,'<a href="\\1" target="_blank" rel="nofollow">\\2</a>',$htm);

//удаление всех ссылок
$htm = preg_replace($pattern,'\\2',$htm);

и т.д.

В общем подставляя \\1 вместо url и \\2 вместо ссылочного текста можно всячески модернизировать текст, данный метод заменяет все вхождения шаблона, т.е. все ссылки.

Пишите комменты, могу написать и другие замены, поиски подстрок и т.д.

вторник, 13 августа 2013 г.

Функция парсинга URL и разбиение

Во время различных обработок может возникнуть необходимость обрабатывать URL, но что делать, если на вход могут подаваться относительные адреса, абсолютные адреса и другое?

Ловите функцию

function parse_address($str)
{
    preg_match("!((http|ftp|https){0,1}://([^/]+))*(/.*)!sim",$str,$a);
    return array('url'=>$a[0],'protocol'=>$a[2],'domain'=>$a[3],'query'=>$a[4]);
}

Данная функция возвращает протокол из юрл, доменное имя и запрос.


Применение:
$u="http://domain.ru/pictures/1.jpg";
$z=parse_address($u);
echo $z['protocol']; //выведет http
echo $z['domain']; //выведет domain.ru
echo $z['query'];  //выведет /pictures/1.jpg


Данная функция применима к относительным и абсолютным URL

Напиcал эту функцию, пока ехал в маршрутке)))

пятница, 7 декабря 2012 г.

PHPExel Wrap + Merge + Auto Height

В  Exel есть такая трабла, для объединенных (merge) ячеек при установке переноса по словам, высота (height) не устанавливается автоматически, но ее можно рассчитать при помощи примерно такого костыля:


$line_height = 12; //высота одной строки текста (one line height)
$in_line = 50; // примерное количество символов для одной строки (chars in one line)

$h = ceil(strlen(utf8_decode($text))/$in_line)*$line_height;

$aSheet->getRowDimension($str_number)->setRowHeight($h);

четверг, 7 июня 2012 г.

WebAsyst ShopScript меню пользователя

В файле /published/SC/html/scripts/modules/test/class.test.php есть такая функция, которая выводит текст Регистрация, Вход с паролем и др, или Мой счет и выход, в зависимости от того авторизованы вы или нет, но что если вы захотите это меню вывести совсем не в списке и убрать всякие другие ссылки?

находим функцию
function cpt_divisions_navigation()
{

list($local_settings) = $this->__getFromStack('call_params');
if(isset($local_settings['local_settings']))$local_settings = $local_settings['local_settings'];
$pages = array();
$SubDivs = &DivisionModule::getBranchDivisions(DivisionModule::getDivisionIDByUnicKey('TitlePage'), array('xEnabled'=>1));
foreach ($SubDivs as $_SubDiv){

if($_SubDiv->UnicKey == 'order_status' && isset($_SESSION["log"])){continue;}

if($_SubDiv->UnicKey == 'auth' && isset($_SESSION["log"]))
{

$login_id = $_SubDiv->ID;
$_SubDiv = DivisionModule::getDivisionByUnicKey('logout');
$_SubDiv->ID = $login_id;
}
if($_SubDiv->UnicKey == 'register' && isset($_SESSION["log"])){

$register_id = $_SubDiv->ID;
$_SubDiv = DivisionModule::getDivisionByUnicKey('office');
$_SubDiv->ID = $register_id;
}
/* @var $_SubDiv Division*/
$pages[] = array(
'id' => $_SubDiv->ID,
'name' => translate($_SubDiv->Name),
'ukey' => $_SubDiv->UnicKey,
);

if(isset($local_settings['divisions']) && $local_settings['divisions']=='mobile' && ($_SubDiv->UnicKey=='office'||$_SubDiv->UnicKey=='register')){
$_SubDiv = DivisionModule::getDivisionByUnicKey('cart');
$pages[] = array(
'id' => $_SubDiv->ID,
'name' => translate(translate($_SubDiv->Name)),
'ukey' => $_SubDiv->UnicKey,
);
}
}

if(!count($pages))return ;

$allowed_pages = explode(':', $local_settings['divisions']);

print '<ul class="'.($local_settings['view'] == 'horizontal'?'horizontal':'vertical').'">';
foreach ($pages as $page){
if(!in_array($page['id'], $allowed_pages) && !(isset($allowed_pages[0]) && $allowed_pages[0]=='mobile'))continue;

print '<li><a href="'.xHtmlSetQuery($page['ukey']?'?ukey='.$page['ukey']:'?did='.$page['id']).'">'.xHtmlSpecialChars($page['name']).'</a></li>';
}
print '</ul>';
}


комментируем ее и ниже пишем свой аналог
function cpt_divisions_navigation()
        {

            if (isset($_SESSION["log"]))
                echo '<a href="/myaccount">Мой кабинет</a> | <a href="/logout">Выйти</a>';
            else
                echo '<a href="/auth">Вход с паролем</a> | <a href="/register">Регистрация</a>';
            
        }

суббота, 23 апреля 2011 г.

Глобальный массив $_SERVER

Оригинальный мануал тут http://php.net/manual/ru/reserved.variables.server.php

Часто в ваших PHP скриптах может потребоваться данная информация, передаваемая сервером.

Данный перечень не полный, по ссылке выше вы найдете гораздо больше и подробней.





$_SERVER['SERVER_ADDR']

покажет IP адрес сервера

$_SERVER['SERVER_NAME']
имя сервера

$_SERVER['HTTP_HOST']
домен, по которому обратились к серверу, например при запросе
http://site.ru/index.php
выдаст site.ru


$_SERVER['SERVER_SOFTWARE']
программное обеспечение сервера, например Apache/2.2.16 (Debian)

$_SERVER['SERVER_PROTOCOL']
HTTP/1.1 протокол сервера


$_SERVER['REQUEST_METHOD']
метод запроса, GET или POST


$_SERVER['REQUEST_TIME']
штамп времени при запуске скрипта

$_SERVER['QUERY_STRING']
строка запроса, например если в строке адреса http://site.ru/index.php?id=5
то покажет id=5

$_SERVER['DOCUMENT_ROOT']
путь до корневой директории сайта на сервере

$_SERVER['HTTP_REFERER']
полный URL, с которого пришел посетитель

$_SERVER['HTTP_USER_AGENT']
клиент пользователя, например
Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20100101 Firefox/4.0

$_SERVER['REMOTE_ADDR']
ip адрес, с которого произошел запрос

$_SERVER['REMOTE_HOST']

имя компьютера, с которого произошел запрос


$_SERVER['REMOTE_PORT']
удаленный порт соединения


$_SERVER['SCRIPT_FILENAME']
полный путь до выполняемого скрипта на сервере
например /var/www/index.php


$_SERVER['SERVER_ADMIN']
мыло админа


$_SERVER['SERVER_PORT']
порт, на котором слушает сервер


$_SERVER['SERVER_SIGNATURE']
полная инфа о сервере, например
Apache/2.2.16 (Debian) Server at www.domain.ru Port 80


$_SERVER['SCRIPT_NAME']
имя скрипта, например при запросе http://domain.ru/test/test.php?id=2
выведет /test/test.php

$_SERVER['REQUEST_URI']
при запросе http://domain.ru/test/test.php?id=5 выведет
/test/test.php?id=5


$_SERVER['PHP_AUTH_USER']
пользователь, который авторизовался через HTTP_AUTH

$_SERVER['PHP_AUTH_PW']
пароль пользователя, авторизовавшегося через HTTP_AUTH

$_SERVER['AUTH_TYPE']
тип авторизации

четверг, 6 января 2011 г.

Поиск по сайту PHP

 Сегодня я покажу вам пример того, как можно сделать поиск по сайту

Если вы делаете что то вроде

SELECT * FROM `products` WHERE  `name` like '%холодильник%';

то вроде как работает, но не совсем корректно

Например мы захотели найти Холодильник STINOL

а у нас товар забит в базе как Холодильник однокамерный STINOL то ни чего не найдет

столкнувшись с этой проблемой, я написал такую функцию


function searchproc ($str)
{
$tmp=""; 
$str=trim($str);
$result = preg_split("/[\s]+/", $str);
$i=0;
while (!empty($result[$i]))
    {
    if ($i>0) {$tmp.= " AND ";}
    $tmp.="( `name` LIKE '%".$result[$i]."%')";
    $i++;
    }
return $tmp;
}



функция делит наш запрос по пробелам и выдает в результате что то вроде
(`name` like '%холодильник%') AND (`name` like '%STINOL%') 
теперь нам остается подставить в строку запроса searchproc ($searchstring) и у нас будет почти хороший поисковик по товарам в каталоге




PS: Данная функция может служить примером, но не стоит её слепо копировать и использовать в своих скриптах, если вписать в строку поиска что то вроде 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
то у нас получается достаточно длинный запрос, что может вызвать ошибку, нужно или обрезать входные данные или делать ограничение на количество проходов цикла в функции

среда, 20 октября 2010 г.

Отправка уведомления о заказе админу в Virtuemart, если покупатель не указал свой email

Если делать в своем магазине процедуру покупки без всяких регистраций и с минимум усилий то скорей всего вам захочется сделать поле e-mail в данных пользователя необязательным, ведь не все имеют свою электронную почту да и не все хотят ее оставлять, вполне достаточно написать в регистрационной форме ФИО и Телефон, а e-mail по желанию.

Но вот ведь незадача! Если пользователь не введет своего емэйла, то и админу тоже не прийдет письмо с уведомлением о заказе. А почему? Сейчас попытаюсь разъяснить.

Открываем файл administrator/components/com_virtuemart/classes/ps_checkout.php

примерно на строках 2160-2162 находим такие две строки
$shopper_mail = vmMail( $from_email, $mosConfig_fromname, $shopper_email, $shopper_subject, $shopper_mail_Body, $shopper_mail_AltBody, true, null, null, $EmbeddedImages);
 
$vendor_mail = vmMail( $shopper_email, $shopper_name, $vendor_email, $vendor_subject, $vendor_mail_Body, $vendor_mail_AltBody, true, null, null, $EmbeddedImages);



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


Удаляем эти две строки и вместо них вставляем следующее содержимое


if (!$shopper_email)

{
$vendor_mail = vmMail( "robot@domain.ru", $shopper_name, $vendor_email, $vendor_subject, $vendor_mail_Body, $vendor_mail_AltBody, true, null, null, $EmbeddedImages);
}


else
{
$shopper_mail = vmMail( $from_email, $mosConfig_fromname, $shopper_email, $shopper_subject, $shopper_mail_Body, $shopper_mail_AltBody, true, null, null, $EmbeddedImages);


$vendor_mail = vmMail( $shopper_email, $shopper_name, $vendor_email, $vendor_subject, $vendor_mail_Body, $vendor_mail_AltBody, true, null, null, $EmbeddedImages);

}


Где robot@domain.ru - адрес, от которого будет отправляться уведомление админу