[{"data":1,"prerenderedAt":1450},["ShallowReactive",2],{"navigation_docs":3,"-modules-problems-portal-check":238,"-modules-problems-portal-check-surround":1447},[4,45,60],{"title":5,"description":6,"icon":7,"path":8,"stem":9,"children":10},"Методология",null,"ruler","\u002Fmethodology","1.methodology",[11,15,20,25,30,35,40],{"title":12,"path":8,"stem":13,"description":14},"bxshef: методология и проверка навыков","1.methodology\u002Findex","Как писать навыки ИИ-агентов для Битрикса и как проверять, что им можно верить",{"title":16,"path":17,"stem":18,"description":19},"Стандарт навыка","\u002Fmethodology\u002Fstandard","1.methodology\u002F1.standard","11 правил, каждое из провала на стенде",{"title":21,"path":22,"stem":23,"description":24},"Методология проверки","\u002Fmethodology\u002Fmethod","1.methodology\u002F2.method","lint → eval → стенд; что измерено",{"title":26,"path":27,"stem":28,"description":29},"bxshef — CLI","\u002Fmethodology\u002Fbxshef","1.methodology\u002F3.bxshef","lint, eval, feedback",{"title":31,"path":32,"stem":33,"description":34},"GitHub Action","\u002Fmethodology\u002Faction","1.methodology\u002F4.action","тот же lint + eval в любом репозитории навыков",{"title":36,"path":37,"stem":38,"description":39},"Заготовка репозитория","\u002Fmethodology\u002Ftemplate","1.methodology\u002F5.template","с чего начать автору модуля",{"title":41,"path":42,"stem":43,"description":44},"Приёмник отзывов","\u002Fmethodology\u002Ffeedback","1.methodology\u002F6.feedback","куда уходят отзывы ИИ-агентов",{"title":46,"description":6,"icon":47,"path":48,"stem":49,"children":50},"Навыки","sparkles","\u002Fskills","2.skills",[51,55],{"title":52,"path":48,"stem":53,"description":54},"Навыки shef.*","2.skills\u002Findex","npx skills add bx-shef\u002Fskills",{"title":56,"path":57,"stem":58,"description":59},"shef-feedback","\u002Fskills\u002Fshef-feedback","2.skills\u002F1.shef-feedback","Отправить отзыв о навыке shef-* или навыке команды. Брать ВСЕГДА, когда просят оставить или отправить отзыв о навыке — даже если сам навык в диалоге не виден, —",{"title":61,"description":6,"icon":62,"path":63,"stem":64,"children":65},"Модули shef.*","package","\u002Fmodules","3.modules",[66,69,131,179],{"title":61,"path":63,"stem":67,"description":68},"3.modules\u002Findex","Что за чем ставить",{"title":70,"description":6,"path":71,"stem":72,"children":73},"shef.options","\u002Fmodules\u002Foptions","3.modules\u002F1.options\u002Findex",[74,76,81,86,91,96,101,106,110,114,119,123,127],{"title":70,"path":71,"stem":72,"description":75},"фундамент: настройки, трейты, компоненты",{"title":77,"path":78,"stem":79,"description":80},"[`\\Shef\\Options\\Installator`] Installer","\u002Fmodules\u002Foptions\u002Finstaller","3.modules\u002F1.options\u002F1.installer","Для облегчения установок.",{"title":82,"path":83,"stem":84,"description":85},"Сборка, CI и релиз","\u002Fmodules\u002Foptions\u002Fbuild-and-install","3.modules\u002F1.options\u002F10.build-and-install","Раскладка репозитория — в module-structure.md, процесс —\nв CONTRIBUTING.md, установка глазами пользователя —\nв README.md.",{"title":87,"path":88,"stem":89,"description":90},"Раскладка репозитория","\u002Fmodules\u002Foptions\u002Fmodule-structure","3.modules\u002F1.options\u002F11.module-structure","Файл про устройство репозитория. Опорные точки модуля — в CLAUDE.md,\nпроцесс — в CONTRIBUTING.md, сборка — в\nbuild-and-install.md.",{"title":92,"path":93,"stem":94,"description":95},"Проверка на портале","\u002Fmodules\u002Foptions\u002Fportal-check","3.modules\u002F1.options\u002F12.portal-check","Всё, что ниже рантайма Битрикса, тестами не закрыть: установка, права, кеш,\nраскладка файлов, поведение при обновлении. Проверять это приходится руками —\nи лучше по списку, потому что забытый шаг находит не разработчик, а клиент.",{"title":97,"path":98,"stem":99,"description":100},"[`\\Shef\\Options\\Main\\Options`] Опции настроек модуля","\u002Fmodules\u002Foptions\u002Foptions","3.modules\u002F1.options\u002F2.options","Поддерживает следующие типы:",{"title":102,"path":103,"stem":104,"description":105},"Работа с пользователями","\u002Fmodules\u002Foptions\u002Fsecurity","3.modules\u002F1.options\u002F3.security","",{"title":107,"path":108,"stem":109,"description":105},"[`\\Shef\\Options\\Main\\Utils`] Утилиты","\u002Fmodules\u002Foptions\u002Futils","3.modules\u002F1.options\u002F4.utils",{"title":111,"path":112,"stem":113,"description":105},"[`\\Shef\\Options\\Components`] Работа с компонентами","\u002Fmodules\u002Foptions\u002Fcomponents","3.modules\u002F1.options\u002F5.components",{"title":115,"path":116,"stem":117,"description":118},"[`\\Shef\\Options\\Options`] Паттерны","\u002Fmodules\u002Foptions\u002Fpattern","3.modules\u002F1.options\u002F6.pattern","Запускаемые примеры: singleton.php,\nconfig.php, smartstd.php —\nкак их гонять, написано в examples\u002FREADME.md.",{"title":120,"path":121,"stem":122,"description":105},"[`\\Shef\\Options\\Tests`] Тестирование","\u002Fmodules\u002Foptions\u002Ftests","3.modules\u002F1.options\u002F7.tests",{"title":124,"path":125,"stem":126,"description":105},"[`\\Shef\\Options\\TraitList`] Набор трейтов","\u002Fmodules\u002Foptions\u002Ftraitlist","3.modules\u002F1.options\u002F8.traitlist",{"title":128,"path":129,"stem":130,"description":105},"Правила для ИИ-агентов в этом репозитории","\u002Fmodules\u002Foptions\u002Fagent-rules","3.modules\u002F1.options\u002F9.agent-rules",{"title":132,"description":6,"path":133,"stem":134,"children":135},"shef.problems","\u002Fmodules\u002Fproblems","3.modules\u002F2.problems\u002Findex",[136,138,143,147,152,157,161,166,169,172,175],{"title":132,"path":133,"stem":134,"description":137},"логи, журнал событий, учёт проблем",{"title":139,"path":140,"stem":141,"description":142},"[`\\Shef\\Problems\\Integration`] События и меню","\u002Fmodules\u002Fproblems\u002Fevents","3.modules\u002F2.problems\u002F1.events","Что модуль регистрирует в ядре при установке. Список — в .settings.php, ключ\ninstallEvents; что каждый обработчик существует, сверяет\ntests\u002Fsettings_test.php.",{"title":144,"path":145,"stem":146,"description":105},"Безопасность логов","\u002Fmodules\u002Fproblems\u002Fsecurity","3.modules\u002F2.problems\u002F10.security",{"title":148,"path":149,"stem":150,"description":151},"Быстрая отладка: `_pr`, `_log`, `_log1`","\u002Fmodules\u002Fproblems\u002Fdeffunctions","3.modules\u002F2.problems\u002F2.deffunctions","Функции объявляет def-functions.php, подключается он из include.php.",{"title":153,"path":154,"stem":155,"description":156},"Уровни логирования","\u002Fmodules\u002Fproblems\u002Floglevel","3.modules\u002F2.problems\u002F3.loglevel","Уровни — стандарт PSR-3, в Monolog это \\Monolog\\Level. Ниже — когда какой брать.",{"title":158,"path":159,"stem":160,"description":105},"[`\\Shef\\Problems\\Integration\\Monolog`] Monolog","\u002Fmodules\u002Fproblems\u002Fmonolog","3.modules\u002F2.problems\u002F4.monolog",{"title":162,"path":163,"stem":164,"description":165},"Ротация логов","\u002Fmodules\u002Fproblems\u002Flogrotate","3.modules\u002F2.problems\u002F5.logrotate","Логи модуля лежат в каталоге логов — по умолчанию на уровень выше корня сайта,\nдля BitrixVM \u002Fhome\u002Fbitrix\u002Fsh_log\u002F*.log, — и сами не чистятся. Ротацию делает\nlogrotate — системная утилита, а не Monolog: Monolog тоже умеет\n(RotatingFileHandler), но тогда за файлами следит каждый PHP-процесс, а не\nодна служба.",{"title":128,"path":167,"stem":168,"description":105},"\u002Fmodules\u002Fproblems\u002Fagent-rules","3.modules\u002F2.problems\u002F6.agent-rules",{"title":82,"path":170,"stem":171,"description":85},"\u002Fmodules\u002Fproblems\u002Fbuild-and-install","3.modules\u002F2.problems\u002F7.build-and-install",{"title":87,"path":173,"stem":174,"description":90},"\u002Fmodules\u002Fproblems\u002Fmodule-structure","3.modules\u002F2.problems\u002F8.module-structure",{"title":92,"path":176,"stem":177,"description":178},"\u002Fmodules\u002Fproblems\u002Fportal-check","3.modules\u002F2.problems\u002F9.portal-check","Всё, что ниже рантайма Битрикса, тестами не закрыть: установка, права, меню,\nраскладка файлов, журнал событий, поведение при обновлении. Проверять это\nприходится руками — и лучше по списку, потому что забытый шаг находит не\nразработчик, а клиент.",{"title":180,"description":6,"path":181,"stem":182,"children":183},"shef.insync","\u002Fmodules\u002Finsync","3.modules\u002F3.insync\u002Findex",[184,186,191,194,198,203,208,213,218,222,227,232,235],{"title":180,"path":181,"stem":182,"description":185},"агенты, импорт, API-клиенты, модели",{"title":187,"path":188,"stem":189,"description":190},"[`\\Shef\\InSync\\Agents`] Агенты","\u002Fmodules\u002Finsync\u002Fagents","3.modules\u002F3.insync\u002F1.agents","Агент импорта — наследник \\Shef\\InSync\\Agents\\AAgent. Описание агента для\nb_agent — \\Shef\\InSync\\Agents\\Entity, установку и управление берёт на себя\n\\Shef\\InSync\\Agents\\Manager.",{"title":87,"path":192,"stem":193,"description":90},"\u002Fmodules\u002Finsync\u002Fmodule-structure","3.modules\u002F3.insync\u002F10.module-structure",{"title":92,"path":195,"stem":196,"description":197},"\u002Fmodules\u002Finsync\u002Fportal-check","3.modules\u002F3.insync\u002F11.portal-check","Всё, что ниже рантайма Битрикса, тестами не закрыть: установка, права, левое\nменю, раскладка компонентов, агенты, таблица импорта, поведение при\nобновлении. Проверять это приходится руками — и лучше по списку, потому что\nзабытый шаг находит не разработчик, а клиент.",{"title":199,"path":200,"stem":201,"description":202},"Безопасность","\u002Fmodules\u002Finsync\u002Fsecurity","3.modules\u002F3.insync\u002F12.security","Модуль даёт другим модулям заготовки для синхронизаций, и самые опасные места\nу него общие с ними: кто может запускать агенты и импорт, что ложится в каталоги\nимпорта, что уходит в SQL и в лог. Ниже — что держит модуль и что остаётся\nпроекту.",{"title":204,"path":205,"stem":206,"description":207},"[`\\Shef\\InSync\\Sync`] Импорт","\u002Fmodules\u002Finsync\u002Fimport","3.modules\u002F3.insync\u002F2.import","Импорт идёт в два шага через таблицу импорта \\Shef\\InSync\\Sync\\Model\\SyncTable\n(shef_insync_model):",{"title":209,"path":210,"stem":211,"description":212},"[`\\Shef\\InSync\\Api`] API","\u002Fmodules\u002Finsync\u002Fapi","3.modules\u002F3.insync\u002F3.api","Обращение к внешнему API по HTTP — наследник \\Shef\\InSync\\Api\\AConnector.",{"title":214,"path":215,"stem":216,"description":217},"[`\\Shef\\InSync\\TraitList\\Xml`] Парсинг XML","\u002Fmodules\u002Finsync\u002Fxml","3.modules\u002F3.insync\u002F4.xml","Разбор XML сделан через SbWereWolf\u002Fxml-navigator\n(статья на Хабре): XMLReader идёт по\nдокументу потоком, а каждый элемент с нужным тегом HierarchyComposer\nпревращает в массив — n имя, v значение, a атрибуты, s вложенные\nэлементы.",{"title":219,"path":220,"stem":221,"description":105},"Компоненты","\u002Fmodules\u002Finsync\u002Fcomponents","3.modules\u002F3.insync\u002F5.components",{"title":223,"path":224,"stem":225,"description":226},"Страницы","\u002Fmodules\u002Finsync\u002Fpage","3.modules\u002F3.insync\u002F6.page","Страницы модуля — в левом меню, штатным разделом intranet\n(Bitrix\\Intranet\\CustomSection): раздел «SH Импорт», код shinsync.\nВерхней панели и shef.uiclear больше нет.",{"title":228,"path":229,"stem":230,"description":231},"[`\\Shef\\InSync\\Main\\Options`] Опции настроек модуля","\u002Fmodules\u002Finsync\u002Foptions","3.modules\u002F3.insync\u002F7.options","Опции для страницы настроек модуля импорта (на ShOptionsConfig из\nshef.options): добавьте их во вкладку своего options_conf.php.",{"title":128,"path":233,"stem":234,"description":105},"\u002Fmodules\u002Finsync\u002Fagent-rules","3.modules\u002F3.insync\u002F8.agent-rules",{"title":82,"path":236,"stem":237,"description":85},"\u002Fmodules\u002Finsync\u002Fbuild-and-install","3.modules\u002F3.insync\u002F9.build-and-install",{"id":239,"title":92,"body":240,"description":178,"extension":1441,"meta":1442,"navigation":1443,"path":176,"rawbody":1444,"seo":1445,"stem":177,"__hash__":1446},"docs\u002F3.modules\u002F2.problems\u002F9.portal-check.md",{"type":241,"value":242,"toc":1425},"minimark",[243,246,254,266,271,357,364,368,371,488,492,499,569,576,610,614,644,694,706,710,713,718,738,753,757,826,834,838,846,883,888,898,902,913,917,973,977,1005,1022,1055,1087,1107,1111,1141,1145,1169,1173,1176,1192,1207,1211,1220,1224,1273,1287,1291,1302,1306,1377,1396,1400,1408,1421],[244,245,178],"p",{},[244,247,248,249,253],{},"Процедура рассчитана на ",[250,251,252],"strong",{},"отдельный стенд",", а не на боевой портал. Шаги\n«удалить модуль» и «поставить на CP1251» на рабочем портале делать нельзя.",[244,255,256,257,261,262,265],{},"Раскладка репозитория — в ",[258,259,260],"a",{"href":173},"module-structure.md",", сборка —\nв ",[258,263,264],{"href":170},"build-and-install.md",".",[267,268,270],"h2",{"id":269},"что-понадобится","Что понадобится",[272,273,274,285],"table",{},[275,276,277],"thead",{},[278,279,280,283],"tr",{},[281,282],"th",{},[281,284],{},[286,287,288,301,316,326,338,346],"tbody",{},[278,289,290,294],{},[291,292,293],"td",{},"портал",[291,295,296,297,300],{},"«коробка» Битрикс24 или БУС, главный модуль ",[250,298,299],{},"22.600.300"," и выше",[278,302,303,306],{},[291,304,305],{},"PHP",[291,307,308,311,312],{},[250,309,310],{},"8.2"," и выше, расширение ",[313,314,315],"code",{},"mbstring",[278,317,318,321],{},[291,319,320],{},"кодировка",[291,322,323],{},[250,324,325],{},"только UTF-8",[278,327,328,332],{},[291,329,330],{},[313,331,70],{},[291,333,334,337],{},[250,335,336],{},"3.0.0"," и выше, установлен",[278,339,340,343],{},[291,341,342],{},"доступ",[291,344,345],{},"администратор портала и доступ к файлам по ssh",[278,347,348,351],{},[291,349,350],{},"архив",[291,352,353,354],{},"со страницы релиза либо собранный ",[313,355,356],{},".\u002Fbuild.sh",[244,358,359,360,363],{},"Для сценария «обновление» нужен стенд, где уже стоит ",[250,361,362],{},"1.x"," — на нём\nпроверяется то, ради чего 2.0.0 сделана мажорной.",[267,365,367],{"id":366},"перед-началом","Перед началом",[244,369,370],{},"Снимите копию каталога модуля и настроек — шаги с удалением необратимы:",[372,373,377],"pre",{"className":374,"code":375,"language":376,"meta":105,"style":105},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","cp -a \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fmodules\u002Fshef.problems \u002Ftmp\u002Fshef.problems.before 2>\u002Fdev\u002Fnull\nmysqldump -u… portal b_option --where=\"MODULE_ID='shef.problems'\" > \u002Ftmp\u002Fopt.before.sql\nmysqldump -u… portal b_module_to_module --where=\"TO_MODULE_ID='shef.problems'\" > \u002Ftmp\u002Fevents.before.sql\nls \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fjs\u002F \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fimages\u002F | sort > \u002Ftmp\u002Fpublic.before\n","bash",[313,378,379,406,439,465],{"__ignoreMap":105},[380,381,384,388,392,396,399,403],"span",{"class":382,"line":383},"line",1,[380,385,387],{"class":386},"sbgvK","cp",[380,389,391],{"class":390},"stzsN"," -a",[380,393,395],{"class":394},"s_sjI"," \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fmodules\u002Fshef.problems",[380,397,398],{"class":394}," \u002Ftmp\u002Fshef.problems.before",[380,400,402],{"class":401},"smGrS"," 2>",[380,404,405],{"class":394},"\u002Fdev\u002Fnull\n",[380,407,409,412,415,418,421,424,428,431,433,436],{"class":382,"line":408},2,[380,410,411],{"class":386},"mysqldump",[380,413,414],{"class":390}," -u…",[380,416,417],{"class":394}," portal",[380,419,420],{"class":394}," b_option",[380,422,423],{"class":390}," --where=",[380,425,427],{"class":426},"sjJ54","\"",[380,429,430],{"class":394},"MODULE_ID='shef.problems'",[380,432,427],{"class":426},[380,434,435],{"class":401}," >",[380,437,438],{"class":394}," \u002Ftmp\u002Fopt.before.sql\n",[380,440,442,444,446,448,451,453,455,458,460,462],{"class":382,"line":441},3,[380,443,411],{"class":386},[380,445,414],{"class":390},[380,447,417],{"class":394},[380,449,450],{"class":394}," b_module_to_module",[380,452,423],{"class":390},[380,454,427],{"class":426},[380,456,457],{"class":394},"TO_MODULE_ID='shef.problems'",[380,459,427],{"class":426},[380,461,435],{"class":401},[380,463,464],{"class":394}," \u002Ftmp\u002Fevents.before.sql\n",[380,466,468,471,474,477,480,483,485],{"class":382,"line":467},4,[380,469,470],{"class":386},"ls",[380,472,473],{"class":394}," \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fjs\u002F",[380,475,476],{"class":394}," \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fimages\u002F",[380,478,479],{"class":401}," |",[380,481,482],{"class":386}," sort",[380,484,435],{"class":401},[380,486,487],{"class":394}," \u002Ftmp\u002Fpublic.before\n",[267,489,491],{"id":490},"_0-архив-тот-самый","0. Архив — тот самый",[244,493,494,495,498],{},"Архив собирается ",[250,496,497],{},"побайтово одинаково"," у всех, кто взял тот же коммит:",[372,500,502],{"className":374,"code":501,"language":376,"meta":105,"style":105},"git clone https:\u002F\u002Fgithub.com\u002Fbx-shef\u002Fproblems.git\ncd problems && git checkout \u003Cтег проверяемой версии>\n.\u002Fbuild.sh                       # последняя строка напечатает sha256\nsha256sum \u002Fпуть\u002Fк\u002Fскачанному\u002Fshef.problems.zip\n",[313,503,504,515,553,561],{"__ignoreMap":105},[380,505,506,509,512],{"class":382,"line":383},[380,507,508],{"class":386},"git",[380,510,511],{"class":394}," clone",[380,513,514],{"class":394}," https:\u002F\u002Fgithub.com\u002Fbx-shef\u002Fproblems.git\n",[380,516,517,521,524,528,531,534,537,540,543,546,550],{"class":382,"line":408},[380,518,520],{"class":519},"sptTA","cd",[380,522,523],{"class":394}," problems",[380,525,527],{"class":526},"sP7_E"," &&",[380,529,530],{"class":386}," git",[380,532,533],{"class":394}," checkout",[380,535,536],{"class":401}," \u003C",[380,538,539],{"class":394},"тег",[380,541,542],{"class":394}," проверяемой",[380,544,545],{"class":394}," верси",[380,547,549],{"class":548},"su5hD","и",[380,551,552],{"class":401},">\n",[380,554,555,557],{"class":382,"line":441},[380,556,356],{"class":386},[380,558,560],{"class":559},"sutJx","                       # последняя строка напечатает sha256\n",[380,562,563,566],{"class":382,"line":467},[380,564,565],{"class":386},"sha256sum",[380,567,568],{"class":394}," \u002Fпуть\u002Fк\u002Fскачанному\u002Fshef.problems.zip\n",[244,570,571,572,575],{},"Хеши обязаны совпасть. Первым уровнем внутри архива — ровно ",[313,573,574],{},"shef.problems\u002F",":",[372,577,579],{"className":374,"code":578,"language":376,"meta":105,"style":105},"unzip -Z1 shef.problems.zip | cut -d\u002F -f1 | sort -u\n",[313,580,581],{"__ignoreMap":105},[380,582,583,586,589,592,594,597,600,603,605,607],{"class":382,"line":383},[380,584,585],{"class":386},"unzip",[380,587,588],{"class":390}," -Z1",[380,590,591],{"class":394}," shef.problems.zip",[380,593,479],{"class":401},[380,595,596],{"class":386}," cut",[380,598,599],{"class":390}," -d\u002F",[380,601,602],{"class":390}," -f1",[380,604,479],{"class":401},[380,606,482],{"class":386},[380,608,609],{"class":390}," -u\n",[267,611,613],{"id":612},"a-чистая-установка","A. Чистая установка",[615,616,617,624,634],"ol",{},[618,619,620,621,623],"li",{},"Убедиться, что ",[313,622,70],{}," стоит и его версия 3.0.0 или выше.",[618,625,626,627,630,631,265],{},"Распаковать в ",[313,628,629],{},"bitrix\u002Fmodules\u002F",", чтобы получилось ",[313,632,633],{},"bitrix\u002Fmodules\u002Fshef.problems\u002F",[618,635,636,639,640,643],{},[250,637,638],{},"Marketplace → Установленные решения"," → «",[380,641,642],{},"SH"," Учёт проблем» → установить.",[244,645,646,649,650,653,654,657,658,661,662,665,666,669,670,673,674,677,678,681,682,685,686,689,690,693],{},[250,647,648],{},"Ожидается:"," «Модуль успешно установлен»; в ",[313,651,652],{},"\u002Fbitrix\u002Fjs\u002Fshef-problems\u002F","\nпоявились два каталога — ",[313,655,656],{},"monolog-pr-html"," и ",[313,659,660],{},"monolog-pr-html-admin","; появился\n",[313,663,664],{},"\u002Fbitrix\u002Fadmin\u002Fshef_problems_logs.php"," — одна строка ",[313,667,668],{},"require"," на\n",[313,671,672],{},"admin\u002Flogs.php"," модуля ",[250,675,676],{},"там, где модуль стоит"," (поставили в\n",[313,679,680],{},"\u002Flocal\u002Fmodules"," — путь ",[313,683,684],{},"\u002Flocal\u002Fmodules\u002F…","); ",[313,687,688],{},"\u002Fbitrix\u002Fimages\u002Fshef.problems"," ",[250,691,692],{},"не","\nпоявился.",[244,695,696,699,700,702,703,705],{},[250,697,698],{},"Отдельно:"," на стенде без ",[313,701,70],{}," (или со старым 2.x) установка\nобязана отказать с текстом про ",[313,704,70],{}," и версию — а не поставиться и\nупасть на первой странице.",[267,707,709],{"id":708},"b-обновление-с-1x-главный-сценарий-200","B. Обновление с 1.x — главный сценарий 2.0.0",[244,711,712],{},"Делается на стенде, где стоит 1.x и настроены сотрудники.",[615,714,715],{},[618,716,717],{},"Запомнить, что было:",[372,719,721],{"className":374,"code":720,"language":376,"meta":105,"style":105},"ls \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fimages\u002Fshef.problems\u002F 2>\u002Fdev\u002Fnull    # в 1.x есть\n",[313,722,723],{"__ignoreMap":105},[380,724,725,727,730,732,735],{"class":382,"line":383},[380,726,470],{"class":386},[380,728,729],{"class":394}," \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fimages\u002Fshef.problems\u002F",[380,731,402],{"class":401},[380,733,734],{"class":394},"\u002Fdev\u002Fnull",[380,736,737],{"class":559},"    # в 1.x есть\n",[615,739,740,747],{"start":408},[618,741,742,743,746],{},"Заменить каталог модуля содержимым новой версии ",[250,744,745],{},"целиком"," (старый убрать,\nновый распаковать): в 1.x в корне модуля лежали файлы, которых больше нет.",[618,748,749,750,265],{},"Открыть ",[313,751,752],{},"\u002Fbitrix\u002Fadmin\u002Fsettings.php?mid=shef.problems",[244,754,755],{},[250,756,648],{},[758,759,760,774,781,784,801,811],"ul",{},[618,761,762,763,766,767,770,771,773],{},"страница открывается. В 1.x ",[313,764,765],{},"options_conf.php"," передавал ",[313,768,769],{},"indexDoc",", и с\n",[313,772,70],{}," 3.x страница падала бы с «Unknown named parameter» — это и\nпроверяем;",[618,775,776,777,780],{},"вкладки «Сотрудники» и «Зависимости»; ранее выбранные сотрудники ",[250,778,779],{},"на\nместе"," — имена настроек не менялись;",[618,782,783],{},"в логе портала нет «class not found» и deprecation от Monolog;",[618,785,786,787,790,791,793,794,796,797,800],{},"если на стенде стоит ",[313,788,789],{},"shef.uiclear"," — в верхней панели пропали пункты\n«",[380,792,642],{}," Логи» и «",[380,795,642],{}," Журналы», и ",[250,798,799],{},"ошибок нет",": обработчик 1.x отвечает\nзаглушкой. Пункты теперь в меню административной части, шаг D.",[618,802,803,804,806,807,810],{},"после первого открытия административной части появился\n",[313,805,664],{},": установщик при замене файлов не\nзапускался, страницу логов кладёт меню (",[313,808,809],{},"AdminMenu::ensureLogsPage()",");",[618,812,813,814,817,818,821,822,825],{},"логи теперь пишутся вне корня сайта — старый ",[313,815,816],{},"\u002Flocal\u002Fsh_log"," остался и\n",[250,819,820],{},"открыт"," веб-серверу: перенесите логи и удалите его, см.\n",[258,823,824],{"href":145},"security.md",", «После обновления с 1.x». Пути в logrotate — тоже.",[244,827,828,833],{},[250,829,830,832],{},[313,831,688],{}," после обновления останется"," — это нормально:\nубирает его деинсталляция, шаг H.",[267,835,837],{"id":836},"c-страница-настроек","C. Страница настроек",[615,839,840,843],{},[618,841,842],{},"Выбрать на вкладке «Сотрудники» разных людей на каждую роль, сохранить.",[618,844,845],{},"Проверить из CLI, что каждая роль читается своя:",[372,847,849],{"className":374,"code":848,"language":376,"meta":105,"style":105},"php -r '$_SERVER[\"DOCUMENT_ROOT\"]=\"\u002Fvar\u002Fwww\u002Fportal\"; define(\"NO_KEEP_STATISTIC\",true); define(\"NOT_CHECK_PERMISSIONS\",true);\nrequire $_SERVER[\"DOCUMENT_ROOT\"].\"\u002Fbitrix\u002Fmodules\u002Fmain\u002Finclude\u002Fprolog_before.php\";\n\\Bitrix\\Main\\Loader::includeModule(\"shef.problems\");\nforeach([\"getDefUserId\",\"getAdminId\",\"getDirectorId\",\"getSyncUserId\",\"getProductsUserId\",\"getSaleUserId\"] as $m) echo $m, \" = \", \\Shef\\Problems\\Main\\Constants::$m(), PHP_EOL;'\n",[313,850,851,865,870,875],{"__ignoreMap":105},[380,852,853,856,859,862],{"class":382,"line":383},[380,854,855],{"class":386},"php",[380,857,858],{"class":390}," -r",[380,860,861],{"class":426}," '",[380,863,864],{"class":394},"$_SERVER[\"DOCUMENT_ROOT\"]=\"\u002Fvar\u002Fwww\u002Fportal\"; define(\"NO_KEEP_STATISTIC\",true); define(\"NOT_CHECK_PERMISSIONS\",true);\n",[380,866,867],{"class":382,"line":408},[380,868,869],{"class":394},"require $_SERVER[\"DOCUMENT_ROOT\"].\"\u002Fbitrix\u002Fmodules\u002Fmain\u002Finclude\u002Fprolog_before.php\";\n",[380,871,872],{"class":382,"line":441},[380,873,874],{"class":394},"\\Bitrix\\Main\\Loader::includeModule(\"shef.problems\");\n",[380,876,877,880],{"class":382,"line":467},[380,878,879],{"class":394},"foreach([\"getDefUserId\",\"getAdminId\",\"getDirectorId\",\"getSyncUserId\",\"getProductsUserId\",\"getSaleUserId\"] as $m) echo $m, \" = \", \\Shef\\Problems\\Main\\Constants::$m(), PHP_EOL;",[380,881,882],{"class":426},"'\n",[244,884,885,887],{},[250,886,648],{}," шесть строк, ID — ровно те, что выбрали.",[244,889,890,891,893,894,897],{},"На вкладке «Сотрудники» — строка «Логи модуля» со ссылкой и каталогом логов:\nссылка открывает ",[313,892,664],{},", каталог — вне корня\nсайта (на BitrixVM ",[313,895,896],{},"\u002Fhome\u002Fbitrix\u002Fsh_log",").",[267,899,901],{"id":900},"d-меню-учёт-проблем","D. Меню «Учёт проблем»",[615,903,904,910],{},[618,905,906,907,265],{},"Под администратором: ",[250,908,909],{},"Настройки → Учёт проблем",[618,911,912],{},"Под пользователем с доступом в админку, но не администратором — то же.",[244,914,915],{},[250,916,648],{},[758,918,919,922,935,938,944,950,964,967],{},[618,920,921],{},"администратору — раздел с группами «Логи», «Журнал событий» и пунктом\n«Настройки модуля»; не администратору — раздела нет;",[618,923,924,925,927,928,931,932,934],{},"«Логи → Все логи» открывает ",[313,926,664],{},": строка\n«Каталог логов: …» — ",[250,929,930],{},"вне корня сайта"," (на BitrixVM ",[313,933,896],{},"),\nниже список файлов; до шага E он может быть пуст;",[618,936,937],{},"пункт отдельного лога открывает конец файла; файла ещё нет — страница\nскажет «файла нет», это нормально до шага E;",[618,939,940,941,943],{},"не администратор, открывший ",[313,942,664],{}," напрямую,\nполучает форму входа, а не лог;",[618,945,946,949],{},[313,947,948],{},"…\u002Fshef_problems_logs.php?file=..\u002Fwww\u002Fbitrix\u002F.settings.php"," — «файла нет», а\nне содержимое настроек;",[618,951,952,955,956,959,960,963],{},[313,953,954],{},"…\u002Fshef_problems_logs.php?file=%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E"," —\nв заголовке страницы ",[313,957,958],{},"\u003Cimg …>"," виден ",[250,961,962],{},"текстом",", окна alert нет;",[618,965,966],{},"пункт журнала открывает журнал событий, отфильтрованный по типу;",[618,968,969,970,265],{},"«Ошибки платёжных систем» есть, только если стоит ",[313,971,972],{},"perfmon",[267,974,976],{"id":975},"e-запись-проблемы","E. Запись проблемы",[372,978,980],{"className":374,"code":979,"language":376,"meta":105,"style":105},"cd problems && DOCUMENT_ROOT=\u002Fvar\u002Fwww\u002Fportal php examples\u002Fproblems.php\n",[313,981,982],{"__ignoreMap":105},[380,983,984,986,988,990,993,996,999,1002],{"class":382,"line":383},[380,985,520],{"class":519},[380,987,523],{"class":394},[380,989,527],{"class":526},[380,991,992],{"class":548}," DOCUMENT_ROOT",[380,994,995],{"class":401},"=",[380,997,998],{"class":394},"\u002Fvar\u002Fwww\u002Fportal",[380,1000,1001],{"class":386}," php",[380,1003,1004],{"class":394}," examples\u002Fproblems.php\n",[244,1006,1007,1009,1010,1013,1014,1017,1018,1021],{},[250,1008,648],{}," все строки ",[313,1011,1012],{},"ok",", последняя — ",[313,1015,1016],{},"ГОТОВО: problems",", первая строка\nзаканчивается на ",[313,1019,1020],{},"[портал]",". После этого:",[758,1023,1024,1043,1050],{},[618,1025,1026,1027,1030,1031,1034,1035,1038,1039,1042],{},"в журнале событий запись типа ",[313,1028,1029],{},"SH_PROBLEMS_SYNC",", модуль ",[313,1032,1033],{},"acme.exchange",",\nэлемент ",[313,1036,1037],{},"1024",", ",[250,1040,1041],{},"важность ERROR"," (не UNKNOWN — запись уровня CRITICAL);",[618,1044,1045,1046,1049],{},"в меню «Учёт проблем → Логи → ",[380,1047,1048],{},"Monolog"," Sh_problems_sync» открывается файл с\nэтой записью;",[618,1051,1052,1053,575],{},"файл лежит ",[250,1054,930],{},[372,1056,1058],{"className":374,"code":1057,"language":376,"meta":105,"style":105},"ls -l \u002Fhome\u002Fbitrix\u002Fsh_log\u002Fsh_problems_sync.log     # есть, владелец — пользователь PHP\nls \u002Fhome\u002Fbitrix\u002Fwww\u002Flocal\u002Fsh_log\u002F 2>\u002Fdev\u002Fnull      # нового файла тут нет\n",[313,1059,1060,1073],{"__ignoreMap":105},[380,1061,1062,1064,1067,1070],{"class":382,"line":383},[380,1063,470],{"class":386},[380,1065,1066],{"class":390}," -l",[380,1068,1069],{"class":394}," \u002Fhome\u002Fbitrix\u002Fsh_log\u002Fsh_problems_sync.log",[380,1071,1072],{"class":559},"     # есть, владелец — пользователь PHP\n",[380,1074,1075,1077,1080,1082,1084],{"class":382,"line":408},[380,1076,470],{"class":386},[380,1078,1079],{"class":394}," \u002Fhome\u002Fbitrix\u002Fwww\u002Flocal\u002Fsh_log\u002F",[380,1081,402],{"class":401},[380,1083,734],{"class":394},[380,1085,1086],{"class":559},"      # нового файла тут нет\n",[244,1088,1089,1090,1093,1094,1097,1098,1100,1101,1103,1104,1106],{},"Файла нет, а пример прошёл — смотрите лог PHP: строка ",[313,1091,1092],{},"shef.problems: запись логгера … не прошла"," скажет почему (",[313,1095,1096],{},"open_basedir"," или права на родительский\nкаталог), см. ",[258,1099,824],{"href":145},". На стенде, обновлённом с\n1.x, старый ",[313,1102,816],{}," остаётся и ",[250,1105,820],{}," веб-серверу — перенесите логи\nи удалите его, там же.",[267,1108,1110],{"id":1109},"f-откуда-взят-monolog","F. Откуда взят Monolog",[372,1112,1114],{"className":374,"code":1113,"language":376,"meta":105,"style":105},"php -r '$_SERVER[\"DOCUMENT_ROOT\"]=\"\u002Fvar\u002Fwww\u002Fportal\"; define(\"NO_KEEP_STATISTIC\",true); define(\"NOT_CHECK_PERMISSIONS\",true);\nrequire $_SERVER[\"DOCUMENT_ROOT\"].\"\u002Fbitrix\u002Fmodules\u002Fmain\u002Finclude\u002Fprolog_before.php\";\n\\Bitrix\\Main\\Loader::includeModule(\"shef.problems\");\necho (new ReflectionClass(\\Monolog\\Logger::class))->getFileName(), PHP_EOL;'\n",[313,1115,1116,1126,1130,1134],{"__ignoreMap":105},[380,1117,1118,1120,1122,1124],{"class":382,"line":383},[380,1119,855],{"class":386},[380,1121,858],{"class":390},[380,1123,861],{"class":426},[380,1125,864],{"class":394},[380,1127,1128],{"class":382,"line":408},[380,1129,869],{"class":394},[380,1131,1132],{"class":382,"line":441},[380,1133,874],{"class":394},[380,1135,1136,1139],{"class":382,"line":467},[380,1137,1138],{"class":394},"echo (new ReflectionClass(\\Monolog\\Logger::class))->getFileName(), PHP_EOL;",[380,1140,882],{"class":426},[244,1142,1143],{},[250,1144,648],{},[758,1146,1147,1154],{},[618,1148,1149,1150,1153],{},"на портале без Composer (или без Monolog в нём) — путь внутри\n",[313,1151,1152],{},"bitrix\u002Fmodules\u002Fshef.problems\u002Fvendor\u002F",";",[618,1155,1156,1157,1160,1161,1164,1165,1168],{},"на портале, где Monolog стоит через Composer проекта и путь к\n",[313,1158,1159],{},"composer.json"," указан в ",[313,1162,1163],{},"\u002Fbitrix\u002F.settings.php"," (ключ ",[313,1166,1167],{},"composer","), — путь\nвнутри vendor проекта.",[267,1170,1172],{"id":1171},"g-вывод-на-экран","G. Вывод на экран",[244,1174,1175],{},"В административной части, под администратором, выполнить в «Командной PHP-строке»:",[372,1177,1180],{"className":1178,"code":1179,"language":855,"meta":105,"style":105},"language-php shiki shiki-themes material-theme-lighter github-light github-dark","\\Bitrix\\Main\\Loader::includeModule('shef.problems');\n\\Shef\\Problems\\Logger::PrHtml->getLogger()->warning('\u003Cb>не жирный\u003C\u002Fb>', ['a' => 1]);\n",[313,1181,1182,1187],{"__ignoreMap":105},[380,1183,1184],{"class":382,"line":383},[380,1185,1186],{},"\\Bitrix\\Main\\Loader::includeModule('shef.problems');\n",[380,1188,1189],{"class":382,"line":408},[380,1190,1191],{},"\\Shef\\Problems\\Logger::PrHtml->getLogger()->warning('\u003Cb>не жирный\u003C\u002Fb>', ['a' => 1]);\n",[244,1193,1194,1196,1197,959,1200,1203,1204,1206],{},[250,1195,648],{}," цветной блок (жёлтый — WARNING), трассировка слева или сверху;\nтекст ",[313,1198,1199],{},"\u003Cb>не жирный\u003C\u002Fb>",[250,1201,1202],{},"как текст",", а не жирным — вывод экранирован.\nНет цвета — не подключились стили: проверьте ",[313,1205,652],{},"\nи сбросьте кеш (Ctrl+F5).",[267,1208,1210],{"id":1209},"h-удаление","H. Удаление",[615,1212,1213],{},[618,1214,1215,639,1217,1219],{},[250,1216,638],{},[380,1218,642],{}," Учёт проблем» → удалить.",[244,1221,1222],{},[250,1223,648],{},[758,1225,1226,1234,1244,1257,1266],{},[618,1227,1228,657,1230,1233],{},[313,1229,652],{},[313,1231,1232],{},"\u002Fbitrix\u002Fimages\u002Fshef.problems\u002F"," удалены;",[618,1235,1236,1237,1240,1241,1243],{},"настроек модуля в ",[313,1238,1239],{},"b_option"," нет, настройки ",[313,1242,70],{}," — на месте;",[618,1245,1246,1247,1250,1251,1253,1254,1256],{},"в ",[313,1248,1249],{},"b_module_to_module"," не осталось обработчиков с ",[313,1252,457],{},"\n— в том числе обработчика ",[313,1255,789],{}," из 1.x;",[618,1258,1259,1261,1262,1265],{},[313,1260,664],{}," удалён, остальные файлы\n",[313,1263,1264],{},"\u002Fbitrix\u002Fadmin\u002F"," на месте. Если перед удалением положить на место заглушки\nсвой файл — он остаётся;",[618,1267,1268,1269,1272],{},"файлы в каталоге логов ",[250,1270,1271],{},"остались",": логи — данные проекта, модуль их не\nтрогает.",[244,1274,1275,1276,1279,1280,1282,1283,1286],{},"Если модуль зависит от других (",[313,1277,1278],{},"shef.*"," с ",[313,1281,132],{}," в ",[313,1284,1285],{},"requireModules","),\nудаление обязано отказать и назвать их.",[267,1288,1290],{"id":1289},"i-портал-в-cp1251","I. Портал в CP1251",[244,1292,1293,1294,1297,1298,1301],{},"Установка обязана отказать с текстом про UTF-8. На современных ядрах ветка\nнедостижима — ",[313,1295,1296],{},"Application::isUtfMode()"," возвращает ",[313,1299,1300],{},"true"," без условий, — тогда\nв бланке отмечается «пропущено», и это верный ответ.",[267,1303,1305],{"id":1304},"j-примеры-на-живом-ядре","J. Примеры на живом ядре",[372,1307,1309],{"className":374,"code":1308,"language":376,"meta":105,"style":105},"for e in problems logger throwable log1; do DOCUMENT_ROOT=\u002Fvar\u002Fwww\u002Fportal php examples\u002F$e.php || echo \"FAIL $e\"; done\n",[313,1310,1311],{"__ignoreMap":105},[380,1312,1313,1317,1320,1323,1325,1328,1331,1334,1336,1339,1341,1343,1345,1347,1350,1353,1356,1359,1362,1365,1368,1370,1372,1374],{"class":382,"line":383},[380,1314,1316],{"class":1315},"sVHd0","for",[380,1318,1319],{"class":548}," e ",[380,1321,1322],{"class":1315},"in",[380,1324,523],{"class":394},[380,1326,1327],{"class":394}," logger",[380,1329,1330],{"class":394}," throwable",[380,1332,1333],{"class":394}," log1",[380,1335,1153],{"class":526},[380,1337,1338],{"class":1315}," do",[380,1340,992],{"class":548},[380,1342,995],{"class":401},[380,1344,998],{"class":394},[380,1346,1001],{"class":386},[380,1348,1349],{"class":394}," examples\u002F",[380,1351,1352],{"class":548},"$e",[380,1354,1355],{"class":394},".php",[380,1357,1358],{"class":401}," ||",[380,1360,1361],{"class":519}," echo",[380,1363,1364],{"class":426}," \"",[380,1366,1367],{"class":394},"FAIL ",[380,1369,1352],{"class":548},[380,1371,427],{"class":426},[380,1373,1153],{"class":526},[380,1375,1376],{"class":1315}," done\n",[244,1378,1379,1381,1382,1385,1386,1038,1389,1392,1393,265],{},[250,1380,648],{}," четыре раза ",[313,1383,1384],{},"ГОТОВО: …",", ни одного ",[313,1387,1388],{},"FAIL",[313,1390,1391],{},"Warning",",\n",[313,1394,1395],{},"Deprecated",[267,1397,1399],{"id":1398},"бланк-результата","Бланк результата",[372,1401,1406],{"className":1402,"code":1404,"language":1405},[1403],"language-text","Версия: ____  Коммит: ____  sha256 архива сошёлся: да \u002F нет\nЯдро main: ____  PHP: ____  shef.options: ____  Composer в проекте: да \u002F нет\nopen_basedir: нет \u002F есть, каталог логов в нём: да \u002F нет\n\n0. Архив .................................. ок \u002F не ок\nA. Чистая установка ....................... ок \u002F не ок\n   без shef.options — отказ ............... ок \u002F не ок\nB. Обновление с 1.x ....................... ок \u002F не ок \u002F нет стенда\nC. Страница настроек ...................... ок \u002F не ок\nD. Меню «Учёт проблем» .................... ок \u002F не ок\nE. Запись проблемы ........................ ок \u002F не ок\n   лог вне корня сайта, путь: ____________ да \u002F нет\nF. Monolog взят из ....................... модуль \u002F Composer\nG. Вывод на экран экранирован ............. ок \u002F не ок\nH. Удаление ............................... ок \u002F не ок\nI. CP1251 ................................. ок \u002F пропущено\nJ. Примеры на живом ядре .................. ок \u002F не ок\n\nЗамечания:\n","text",[313,1407,1404],{"__ignoreMap":105},[1409,1410,1411],"note",{},[244,1412,1413,1414,1420],{},"Источник: ",[258,1415,1419],{"href":1416,"rel":1417},"https:\u002F\u002Fgithub.com\u002Fbx-shef\u002Fproblems\u002Fblob\u002Fmain\u002Fdocs\u002Fportal-check.md",[1418],"nofollow","problems\u002Fdocs\u002Fportal-check.md"," — правки туда, сайт пересобирается сам.",[1422,1423,1424],"style",{},"html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}",{"title":105,"searchDepth":441,"depth":441,"links":1426},[1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440],{"id":269,"depth":408,"text":270},{"id":366,"depth":408,"text":367},{"id":490,"depth":408,"text":491},{"id":612,"depth":408,"text":613},{"id":708,"depth":408,"text":709},{"id":836,"depth":408,"text":837},{"id":900,"depth":408,"text":901},{"id":975,"depth":408,"text":976},{"id":1109,"depth":408,"text":1110},{"id":1171,"depth":408,"text":1172},{"id":1209,"depth":408,"text":1210},{"id":1289,"depth":408,"text":1290},{"id":1304,"depth":408,"text":1305},{"id":1398,"depth":408,"text":1399},"md",{},true,"---\ntitle: \"Проверка на портале\"\n---\n\nВсё, что ниже рантайма Битрикса, тестами не закрыть: установка, права, меню,\nраскладка файлов, журнал событий, поведение при обновлении. Проверять это\nприходится руками — и лучше по списку, потому что забытый шаг находит не\nразработчик, а клиент.\n\nПроцедура рассчитана на **отдельный стенд**, а не на боевой портал. Шаги\n«удалить модуль» и «поставить на CP1251» на рабочем портале делать нельзя.\n\nРаскладка репозитория — в [module-structure.md](\u002Fmodules\u002Fproblems\u002Fmodule-structure), сборка —\nв [build-and-install.md](\u002Fmodules\u002Fproblems\u002Fbuild-and-install).\n\n## Что понадобится\n\n| | |\n|---|---|\n| портал | «коробка» Битрикс24 или БУС, главный модуль **22.600.300** и выше |\n| PHP | **8.2** и выше, расширение `mbstring` |\n| кодировка | **только UTF-8** |\n| `shef.options` | **3.0.0** и выше, установлен |\n| доступ | администратор портала и доступ к файлам по ssh |\n| архив | со страницы релиза либо собранный `.\u002Fbuild.sh` |\n\nДля сценария «обновление» нужен стенд, где уже стоит **1.x** — на нём\nпроверяется то, ради чего 2.0.0 сделана мажорной.\n\n## Перед началом\n\nСнимите копию каталога модуля и настроек — шаги с удалением необратимы:\n\n```bash\ncp -a \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fmodules\u002Fshef.problems \u002Ftmp\u002Fshef.problems.before 2>\u002Fdev\u002Fnull\nmysqldump -u… portal b_option --where=\"MODULE_ID='shef.problems'\" > \u002Ftmp\u002Fopt.before.sql\nmysqldump -u… portal b_module_to_module --where=\"TO_MODULE_ID='shef.problems'\" > \u002Ftmp\u002Fevents.before.sql\nls \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fjs\u002F \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fimages\u002F | sort > \u002Ftmp\u002Fpublic.before\n```\n\n## 0. Архив — тот самый\n\nАрхив собирается **побайтово одинаково** у всех, кто взял тот же коммит:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fbx-shef\u002Fproblems.git\ncd problems && git checkout \u003Cтег проверяемой версии>\n.\u002Fbuild.sh                       # последняя строка напечатает sha256\nsha256sum \u002Fпуть\u002Fк\u002Fскачанному\u002Fshef.problems.zip\n```\n\nХеши обязаны совпасть. Первым уровнем внутри архива — ровно `shef.problems\u002F`:\n\n```bash\nunzip -Z1 shef.problems.zip | cut -d\u002F -f1 | sort -u\n```\n\n## A. Чистая установка\n\n1. Убедиться, что `shef.options` стоит и его версия 3.0.0 или выше.\n2. Распаковать в `bitrix\u002Fmodules\u002F`, чтобы получилось `bitrix\u002Fmodules\u002Fshef.problems\u002F`.\n3. **Marketplace → Установленные решения** → «[SH] Учёт проблем» → установить.\n\n**Ожидается:** «Модуль успешно установлен»; в `\u002Fbitrix\u002Fjs\u002Fshef-problems\u002F`\nпоявились два каталога — `monolog-pr-html` и `monolog-pr-html-admin`; появился\n`\u002Fbitrix\u002Fadmin\u002Fshef_problems_logs.php` — одна строка `require` на\n`admin\u002Flogs.php` модуля **там, где модуль стоит** (поставили в\n`\u002Flocal\u002Fmodules` — путь `\u002Flocal\u002Fmodules\u002F…`); `\u002Fbitrix\u002Fimages\u002Fshef.problems` **не**\nпоявился.\n\n**Отдельно:** на стенде без `shef.options` (или со старым 2.x) установка\nобязана отказать с текстом про `shef.options` и версию — а не поставиться и\nупасть на первой странице.\n\n## B. Обновление с 1.x — главный сценарий 2.0.0\n\nДелается на стенде, где стоит 1.x и настроены сотрудники.\n\n1. Запомнить, что было:\n\n```bash\nls \u002Fvar\u002Fwww\u002Fportal\u002Fbitrix\u002Fimages\u002Fshef.problems\u002F 2>\u002Fdev\u002Fnull    # в 1.x есть\n```\n\n2. Заменить каталог модуля содержимым новой версии **целиком** (старый убрать,\n   новый распаковать): в 1.x в корне модуля лежали файлы, которых больше нет.\n3. Открыть `\u002Fbitrix\u002Fadmin\u002Fsettings.php?mid=shef.problems`.\n\n**Ожидается:**\n\n* страница открывается. В 1.x `options_conf.php` передавал `indexDoc`, и с\n  `shef.options` 3.x страница падала бы с «Unknown named parameter» — это и\n  проверяем;\n* вкладки «Сотрудники» и «Зависимости»; ранее выбранные сотрудники **на\n  месте** — имена настроек не менялись;\n* в логе портала нет «class not found» и deprecation от Monolog;\n* если на стенде стоит `shef.uiclear` — в верхней панели пропали пункты\n  «[SH] Логи» и «[SH] Журналы», и **ошибок нет**: обработчик 1.x отвечает\n  заглушкой. Пункты теперь в меню административной части, шаг D.\n\n* после первого открытия административной части появился\n  `\u002Fbitrix\u002Fadmin\u002Fshef_problems_logs.php`: установщик при замене файлов не\n  запускался, страницу логов кладёт меню (`AdminMenu::ensureLogsPage()`);\n* логи теперь пишутся вне корня сайта — старый `\u002Flocal\u002Fsh_log` остался и\n  **открыт** веб-серверу: перенесите логи и удалите его, см.\n  [security.md](\u002Fmodules\u002Fproblems\u002Fsecurity), «После обновления с 1.x». Пути в logrotate — тоже.\n\n**`\u002Fbitrix\u002Fimages\u002Fshef.problems` после обновления останется** — это нормально:\nубирает его деинсталляция, шаг H.\n\n## C. Страница настроек\n\n1. Выбрать на вкладке «Сотрудники» разных людей на каждую роль, сохранить.\n2. Проверить из CLI, что каждая роль читается своя:\n\n```bash\nphp -r '$_SERVER[\"DOCUMENT_ROOT\"]=\"\u002Fvar\u002Fwww\u002Fportal\"; define(\"NO_KEEP_STATISTIC\",true); define(\"NOT_CHECK_PERMISSIONS\",true);\nrequire $_SERVER[\"DOCUMENT_ROOT\"].\"\u002Fbitrix\u002Fmodules\u002Fmain\u002Finclude\u002Fprolog_before.php\";\n\\Bitrix\\Main\\Loader::includeModule(\"shef.problems\");\nforeach([\"getDefUserId\",\"getAdminId\",\"getDirectorId\",\"getSyncUserId\",\"getProductsUserId\",\"getSaleUserId\"] as $m) echo $m, \" = \", \\Shef\\Problems\\Main\\Constants::$m(), PHP_EOL;'\n```\n\n**Ожидается:** шесть строк, ID — ровно те, что выбрали.\n\nНа вкладке «Сотрудники» — строка «Логи модуля» со ссылкой и каталогом логов:\nссылка открывает `\u002Fbitrix\u002Fadmin\u002Fshef_problems_logs.php`, каталог — вне корня\nсайта (на BitrixVM `\u002Fhome\u002Fbitrix\u002Fsh_log`).\n\n## D. Меню «Учёт проблем»\n\n1. Под администратором: **Настройки → Учёт проблем**.\n2. Под пользователем с доступом в админку, но не администратором — то же.\n\n**Ожидается:**\n\n* администратору — раздел с группами «Логи», «Журнал событий» и пунктом\n  «Настройки модуля»; не администратору — раздела нет;\n* «Логи → Все логи» открывает `\u002Fbitrix\u002Fadmin\u002Fshef_problems_logs.php`: строка\n  «Каталог логов: …» — **вне корня сайта** (на BitrixVM `\u002Fhome\u002Fbitrix\u002Fsh_log`),\n  ниже список файлов; до шага E он может быть пуст;\n* пункт отдельного лога открывает конец файла; файла ещё нет — страница\n  скажет «файла нет», это нормально до шага E;\n* не администратор, открывший `\u002Fbitrix\u002Fadmin\u002Fshef_problems_logs.php` напрямую,\n  получает форму входа, а не лог;\n* `…\u002Fshef_problems_logs.php?file=..\u002Fwww\u002Fbitrix\u002F.settings.php` — «файла нет», а\n  не содержимое настроек;\n* `…\u002Fshef_problems_logs.php?file=%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E` —\n  в заголовке страницы `\u003Cimg …>` виден **текстом**, окна alert нет;\n* пункт журнала открывает журнал событий, отфильтрованный по типу;\n* «Ошибки платёжных систем» есть, только если стоит `perfmon`.\n\n## E. Запись проблемы\n\n```bash\ncd problems && DOCUMENT_ROOT=\u002Fvar\u002Fwww\u002Fportal php examples\u002Fproblems.php\n```\n\n**Ожидается:** все строки `ok`, последняя — `ГОТОВО: problems`, первая строка\nзаканчивается на `[портал]`. После этого:\n\n* в журнале событий запись типа `SH_PROBLEMS_SYNC`, модуль `acme.exchange`,\n  элемент `1024`, **важность ERROR** (не UNKNOWN — запись уровня CRITICAL);\n* в меню «Учёт проблем → Логи → [Monolog] Sh_problems_sync» открывается файл с\n  этой записью;\n* файл лежит **вне корня сайта**:\n\n```bash\nls -l \u002Fhome\u002Fbitrix\u002Fsh_log\u002Fsh_problems_sync.log     # есть, владелец — пользователь PHP\nls \u002Fhome\u002Fbitrix\u002Fwww\u002Flocal\u002Fsh_log\u002F 2>\u002Fdev\u002Fnull      # нового файла тут нет\n```\n\nФайла нет, а пример прошёл — смотрите лог PHP: строка `shef.problems: запись\nлоггера … не прошла` скажет почему (`open_basedir` или права на родительский\nкаталог), см. [security.md](\u002Fmodules\u002Fproblems\u002Fsecurity). На стенде, обновлённом с\n1.x, старый `\u002Flocal\u002Fsh_log` остаётся и **открыт** веб-серверу — перенесите логи\nи удалите его, там же.\n\n## F. Откуда взят Monolog\n\n```bash\nphp -r '$_SERVER[\"DOCUMENT_ROOT\"]=\"\u002Fvar\u002Fwww\u002Fportal\"; define(\"NO_KEEP_STATISTIC\",true); define(\"NOT_CHECK_PERMISSIONS\",true);\nrequire $_SERVER[\"DOCUMENT_ROOT\"].\"\u002Fbitrix\u002Fmodules\u002Fmain\u002Finclude\u002Fprolog_before.php\";\n\\Bitrix\\Main\\Loader::includeModule(\"shef.problems\");\necho (new ReflectionClass(\\Monolog\\Logger::class))->getFileName(), PHP_EOL;'\n```\n\n**Ожидается:**\n\n* на портале без Composer (или без Monolog в нём) — путь внутри\n  `bitrix\u002Fmodules\u002Fshef.problems\u002Fvendor\u002F`;\n* на портале, где Monolog стоит через Composer проекта и путь к\n  `composer.json` указан в `\u002Fbitrix\u002F.settings.php` (ключ `composer`), — путь\n  внутри vendor проекта.\n\n## G. Вывод на экран\n\nВ административной части, под администратором, выполнить в «Командной PHP-строке»:\n\n```php\n\\Bitrix\\Main\\Loader::includeModule('shef.problems');\n\\Shef\\Problems\\Logger::PrHtml->getLogger()->warning('\u003Cb>не жирный\u003C\u002Fb>', ['a' => 1]);\n```\n\n**Ожидается:** цветной блок (жёлтый — WARNING), трассировка слева или сверху;\nтекст `\u003Cb>не жирный\u003C\u002Fb>` виден **как текст**, а не жирным — вывод экранирован.\nНет цвета — не подключились стили: проверьте `\u002Fbitrix\u002Fjs\u002Fshef-problems\u002F`\nи сбросьте кеш (Ctrl+F5).\n\n## H. Удаление\n\n1. **Marketplace → Установленные решения** → «[SH] Учёт проблем» → удалить.\n\n**Ожидается:**\n\n* `\u002Fbitrix\u002Fjs\u002Fshef-problems\u002F` и `\u002Fbitrix\u002Fimages\u002Fshef.problems\u002F` удалены;\n* настроек модуля в `b_option` нет, настройки `shef.options` — на месте;\n* в `b_module_to_module` не осталось обработчиков с `TO_MODULE_ID='shef.problems'`\n  — в том числе обработчика `shef.uiclear` из 1.x;\n* `\u002Fbitrix\u002Fadmin\u002Fshef_problems_logs.php` удалён, остальные файлы\n  `\u002Fbitrix\u002Fadmin\u002F` на месте. Если перед удалением положить на место заглушки\n  свой файл — он остаётся;\n* файлы в каталоге логов **остались**: логи — данные проекта, модуль их не\n  трогает.\n\nЕсли модуль зависит от других (`shef.*` с `shef.problems` в `requireModules`),\nудаление обязано отказать и назвать их.\n\n## I. Портал в CP1251\n\nУстановка обязана отказать с текстом про UTF-8. На современных ядрах ветка\nнедостижима — `Application::isUtfMode()` возвращает `true` без условий, — тогда\nв бланке отмечается «пропущено», и это верный ответ.\n\n## J. Примеры на живом ядре\n\n```bash\nfor e in problems logger throwable log1; do DOCUMENT_ROOT=\u002Fvar\u002Fwww\u002Fportal php examples\u002F$e.php || echo \"FAIL $e\"; done\n```\n\n**Ожидается:** четыре раза `ГОТОВО: …`, ни одного `FAIL`, `Warning`,\n`Deprecated`.\n\n## Бланк результата\n\n```\nВерсия: ____  Коммит: ____  sha256 архива сошёлся: да \u002F нет\nЯдро main: ____  PHP: ____  shef.options: ____  Composer в проекте: да \u002F нет\nopen_basedir: нет \u002F есть, каталог логов в нём: да \u002F нет\n\n0. Архив .................................. ок \u002F не ок\nA. Чистая установка ....................... ок \u002F не ок\n   без shef.options — отказ ............... ок \u002F не ок\nB. Обновление с 1.x ....................... ок \u002F не ок \u002F нет стенда\nC. Страница настроек ...................... ок \u002F не ок\nD. Меню «Учёт проблем» .................... ок \u002F не ок\nE. Запись проблемы ........................ ок \u002F не ок\n   лог вне корня сайта, путь: ____________ да \u002F нет\nF. Monolog взят из ....................... модуль \u002F Composer\nG. Вывод на экран экранирован ............. ок \u002F не ок\nH. Удаление ............................... ок \u002F не ок\nI. CP1251 ................................. ок \u002F пропущено\nJ. Примеры на живом ядре .................. ок \u002F не ок\n\nЗамечания:\n```\n\n::note\nИсточник: [problems\u002Fdocs\u002Fportal-check.md](https:\u002F\u002Fgithub.com\u002Fbx-shef\u002Fproblems\u002Fblob\u002Fmain\u002Fdocs\u002Fportal-check.md) — правки туда, сайт пересобирается сам.\n::\n\n",{"title":92,"description":178},"hYIonkf7BSLClf4rmxt4tpVUnDN389V4iJWyRAWN3Q8",[1448,1449],{"title":87,"path":173,"stem":174,"description":90,"children":-1},{"title":180,"path":181,"stem":182,"description":185,"children":-1},1790857269545]