Bitrix: Пакетное выполнение SQL скриптов
/** * @param $pathToScript * $pathToScript = $_SERVER["DOCUMENT_ROOT"]."/local/modules/[modname]/install/sql/b_table.sql"; * */ protected function runSqlScript($pathToScript){ global $DB; $arErrors = $DB->RunSqlBatch($pathToScript); return $arErrors; }
Магазин: Получить список файлов в директории
Получить список файлов в директории
use \Bitrix\Main\IO\Directory; use \Bitrix\Main\Diag\Debug; $dir = new Directory(dirname(__FILE__)); $arDir = $dir->getChildren(); foreach($arDir as $dirItem){ if ($dirItem->isFile() && $dirItem->getName()!="index.php" ) $arMigrations[] = $dirItem->getName(); } Debug::dump($arMigrations);
Пишем в лог
Последнее время мне частенько приходится писать в лог, при этом не имея штатных классов записи в лог, по сему делаю себе ещё одну памятку.
if (!class_exists('Log')) { /** * Class Log * @singleton * @example Log::getInstance()->write("Всё хорошо прошло )) "); */ class Log{ protected static $instance = null; protected static $fileName = "/codeception.log"; protected function __construct(){ } public function getInstance(){ if (empty(static::$instance)){ static::$instance = new static(); } return static::$instance; } protected function getFullFileName(){ return $_SERVER["DOCUMENT_ROOT"].static::$fileName; } public function write($arg) { $strArg = ""; $fp = fopen($this->getFullFileName(), 'a+'); if (is_array($arg)){ $strArg = $this->ar2s($arg); } else { $strArg = $arg; } fwrite($fp, $strArg); fclose($fp); } /** * @param $ar * конвертируем массив в строку */ public function ar2s($ar){ return var_export($ar,true); } } }
phantomjs: примеры
Перед тем как будем использовать фантом его надо запустить как демона
phantomjs --webdriver=4444 > /dev/null &
На данном этапе в интернете есть примеры, но все они довольно однобоки.
Наша же цель автоматизировать «функциональное» тестирование.
В кавычки взято потому что под функциональным тестированием в данном случае понимаем Acceptance (приёмочные) тесты
аля Hello world!
console.log("Hello from PhantomJS"); console.log("\t\t adeveloper"); phantom.exit(0);
тест страницы сайта
var page = require('webpage').create(); var config = { url:"http://shop.dev:8888/", screenshotName:"shopdev.png", viewportSize:{width:1024,height:768} }; //> размер экрана для скриншота page.viewportSize = config.viewportSize; page.open(config.url, function() { console.log("connected to :\t"+config.url); page.render(config.screenshotName); console.log("rendered screenshot :\t"+config.screenshotName); phantom.exit(0); });
CodeCeption
Первые шаги к Continiues Integration
стандартный конфиг CodeCeption для функционального тестирования
class_name: AcceptanceTester modules: enabled: - WebDriver config: WebDriver: url: 'http://www.stmegi.com/' browser: 'PhpBrowser' window_size: 1280x768 curl: CURLOPT_RETURNTRANSFER: true clear_cookies: true // очистка куков между тестами cookies: Name: region Value: moscow capabilities: unexpectedAlertBehaviour: 'accept'
настройки работы в связке с phantomJS
modules: enabled: - WebDriver: url: 'http://group.ru/' browser: phantomjs browserConnectionEnabled: true # - PhpBrowser: # url: http://group.ru/ - \Helper\Acceptance
Функциональное(приёмочное) тестирование
команда запуска теста
./codecept run acceptance --steps --env phantom
запуск конкретного одного теста
пока пишем тесты не удобно запуска весь блок тестов, поэтому запускаем один тест над которым в данный момент работаем, делается это так
./codecept run acceptance FormFeedback --steps -d
маленькая памятка по методам
$I->amOnPage('/'); // я на такой-то странице $I->see('Proxima'); // я ищу на странице текст Proxima $I->seeElement('a.ask'); // я ищу на странице элемент с селектором таким-то
вывод отладочной информации при включённом ключе — —debug
\Codeception\Util\Debug::debug($arg);
добавляем новый приёмочный тест
php codecept generate:cept acceptance FormFeedback # или так ./vendor/bin/codecept generate:cept acceptance FormFeedback
Документация
iOS hide keyboard
UITextViewDelegate
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { if(text == "\n") { textView.resignFirstResponder() return false } return true }
но это не выход если вам нужно
Интернет магазин: склонения
Склонения числительных
/** * Функция склонения числительных в русском языке * * @param int $number Число которое нужно просклонять * @param array $titles Массив слов для склонения * @return string * @example: echo 'Я знаю '.declOfNum(5, array('язык', 'языка', 'языков')); */ function declOfNum($number, $titles) { $cases = array (2, 0, 1, 1, 1, 2); return $titles[ ($number%100 > 4 && $number %100 < 20) ? 2 : $cases[min($number%10, 5)] ]; }
Склонения существительных
я использовал библиотеку phpMorphy
Нативная выборка свойства строка
Нативная выборка свойства строка из таблицы инфоблоков
select e.ID as ORDER_ID, biep.VALUE EMAIL from b_iblock_element e INNER JOIN b_iblock_element_property biep ON e.ID = biep.IBLOCK_ELEMENT_ID WHERE e.IBLOCK_ID=11 AND biep.IBLOCK_PROPERTY_ID = 36
Выборка свойства типа привязка к элементу одиночная
select e.ID as ORDER_ID, biep.VALUE from b_iblock_element e INNER JOIN b_iblock_element_property biep ON e.ID = biep.IBLOCK_ELEMENT_ID WHERE e.IBLOCK_ID=11 AND biep.IBLOCK_PROPERTY_ID = 46
Выборка множественного свойства привязка к элементу
select e.ID as ORDER_ID, biep.VALUE, e2.NAME from b_iblock_element e INNER JOIN b_iblock_element_property biep ON e.ID = biep.IBLOCK_ELEMENT_ID INNER JOIN b_iblock_element e2 ON e2.ID = biep.VALUE WHERE e.IBLOCK_ID=11 AND biep.IBLOCK_PROPERTY_ID = 49
Bitrix: Запросы к БД
Запросы к БД
use Bitrix\Main\Application; use Bitrix\Main\Diag\Debug; $record = Application::getConnection() ->query("select 1+1;") ->fetch(); Debug::writeToFile($record);
Интернет магазин: формат цены
$formattedPrice = number_format($price, 0, '.', ' ').' р.';
Smarty: var_dump
{$item|@var_dump}
!Важно: пробелов не должно быть в этой записи
Создать переменную в шаблоне для каких-то вычислений бывает полезно.
{assign var=hashID value='0'} {$hashID|var_dump}
Skills
Мои навыки и опыт работы
| Навык | Уровень владения |
| Patterns | 5/24 |
| VueJS | 42% |
| Swift | 87% |
| Objective-C | 34% |
| Jade | 98% |
| Git | 86% |
| Python | 54% |
| MySQL | 52% |
В ящик невостребованных навыков
| Bitrix | 80% |
| HostCMS | 51% |
| CodeCeption | 22% |
| PhantomJS | 15% |
| Oracle Database | 14% |
| AngularJS | 38% |
| Smarty | 64% |
Keywords:
Synx
- VIPER
- Generamba
—
NotificationCenter
описываем действие которое сработает как только будет принято сообщение
func actionHandler(){ print("It's work!") }
добавляем наблюдателя и обработчик события/оповещения
NotificationCenter.default.addObserver(self, selector: #selector(actionHandler), name: Notification.Name(rawValue: eventName), object: nil)
Послываем сообщение которое примет центр и передаст обработчику
NotificationCenter.default.post(name: Notification.Name(rawValue: eventName), object: nil)
Поиск файлов по тексту
grep -rn -C 3 --include="*.php" <search_text> /path или grep --exclude-dir=logs -r -n -C 3 <search_text> /path
пример
ищем файлы по маске и содержанию
find ./ -type f -name "*lib*.php" -exec grep -nH "anonse" {} \;
-H выведет путь к файлу
-n выведет номер строки
-C 3 выведет соседние строки
