تحية للجميع.عندما كنت أبحث عن معلومات حول تسجيل الدخول (تدقيق الأحداث) في Bitrix ، لم يكن هناك أي شيء في Habr ، ولكن كان هناك شيء آخر ، ولكن من سيجدها هناك؟لتجديد قاعدة المعرفة ، قررت أن أكتب هذا المقال: شارك تجربتي وحذر من أشعل النار.صياغة المشكلة
كانت مهمتي هي تطوير أبسط نظام محاسبي للهياكل الإعلانية ، بموجب شروط عقد الدولة ، يجب أن يعمل النظام على أساس Bitrix (الإصدار 15).كان من الممكن ركوب كل شيء على جانب Bitrix ، لكنني قررت أنه سيكون غير أمين للغاية فيما يتعلق بالعميل ، تم استخدام وظائف Bitrix إلى أقصى حد:- مصادقة المستخدم
- نظام تخزين البيانات (EAV)
- محرر البيانات
- معالجات أحداث المراجعة
- قدوة لتفويض إجراءات المستخدم
- إدارةالمستخدم
- العمل مع الدلائل
تتناول هذه المقالة بشكل أساسي أحداث المراجعة ، وسأتحدث أيضًا قليلاً عن التفويض وإضافة إشارات مرجعية مخصصة إلى بطاقة تسجيل كتلة المعلومات.أحداث المراجعة
في النظام المطور ، يتم العمل مع البيانات من خلال واجهة برمجة التطبيقات (إضافة كائن جديد إلى الخريطة وتغيير إحداثياته) ، ويتم تحرير معلمات الكائن الأخرى من خلال محرر Bitrix ، نظرًا لأن API لا تعالج جميع طلبات تغيير البيانات ، فلن يكتمل التدقيق في واجهة برمجة التطبيقات فقط ، مما يعني نحتاج إلى مراجعة على جانب Bitrix.ليس الأمر أنني لم أكن أعرف ما هو التدقيق ، ولكن ليس علي أن أكتبه كثيرًا. عادة يتم حل هذا عن طريق كتابة الإصدار القديم من الصف (البيانات القديمة) في جدول منفصل ، ويتم التنفيذ بالكامل على جانب DBMS. علاوة على ذلك ، لدينا في نفس الوقت حالة قبل التغييرات وحالة بعد التغييرات.لكتابة تدقيق على مشغلات DBMS ، أو لكتابة تدقيق على أحداث Bitrix ، فإن الفرق ليس كبيرًا.يتم تسجيل أحداث المعالجة في البرنامج النصي "bitrix / php_interface / init.php "، إذا لم يكن هناك ملف ، فأنت بحاجة إلى إنشائه:use Topliner\Scheme\Logger;
require_once($_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php');
if (!defined('IBLOCK_MODULE')) {
define('IBLOCK_MODULE', 'iblock');
}
AddEventHandler(IBLOCK_MODULE, 'OnIBlockElementAdd',
Array(Logger::class, 'OnAdd'));
هذا مثال على معالج واحد ، في تنفيذي هناك العديد منها ، يمكن عرض الرمز في المستودع ، سيكون الرابط في نهاية المقالة.يحتوي توقيع طريقة معالجة الحدث لكل حدث على خاصته ، والتي ننظر إليها تحديدًا في وثائق Bitrix أو ظهورها الأول ونلقي نظرة على المصادر (بشكل أكثر وضوحًا ، يمكن أيضًا رؤية جميع الأحداث ولحظات معالجات الاتصال في المصادر أثناء تصحيح الأخطاء).وهنا نواجه حقيقة أنه عند العمل مع DBMS ، لدينا كل من البيانات (القديمة) الحالية والبيانات التي سيتم تسجيلها (جديدة) ، وعند العمل مع Bitrix ، لدينا إما بيانات قديمة أو بيانات جديدة ، ولكن ليس عندما لن يكون هناك قديم وجديد في نفس الوقت.مشكلة أخرى هي أن هناك العديد من الأحداث قبل تغيير البيانات ، ولم أتمكن من فهم الاختلاف بينهما ، القصة نفسها تدور حول إطلاق العديد من الأحداث بعد تغيير البيانات ، والعيون تحدق من ثروة الاختيار ، في الواقع هو مجرد وهم الاختيار.رأيي المتواضع حول Bitrix, , _ , ( Delphi PHP), .
depricated «», .
« » ( ) «» (, , ) , . , «» .
, :)
, , , , , , , ? .
باستخدام الدولة العالمية
لحفظ وتمرير الحالة بين معالجات الأحداث ، يجب أن يكون لديك متغيرات عامة. المتغيرات العامة هي شيء لا يمكن إعادة هيكلته ، لذلك أستخدم الخصائص الثابتة للفئة:class Logger
{
const CHANGE = 'change';
const REMOVE = 'remove';
const CREATE = 'create';
const UNDEFINED = 'undefined';
public static $operation = self::UNDEFINED;
const NO_VALUE = [];
private static $fields = self::NO_VALUE;
private static $properties = self::NO_VALUE;
private static $names = self::NO_VALUE;
}
هنا تحتاج إلى تقديم تفسير حول استخدام "الحقول" و "الخصائص". الحقول هي المعلمات التي يحتوي عليها كل إدخال كتلة غير حصرية (معرف ، اسم ، وعلامة غير رئيسية ") ، والخصائص هي معلمات خاصة بسجلات نوع معين من القطع غير المرئي ، في نموذج EAV ، هذه سمات وقيمها."الأسماء" هي أسماء السمات ، في أحد الأحداث لدينا معرفات للسمات والأسماء ، وفي حدث آخر ليس لدينا سوى معرفات ، ولحساب جميل في المجلة ، نحتاج إلى حفظ الأسماء (يمكننا بالطبع طرح المعرّف ، ولكن لسبب ما لا تريده)."العملية" هي العملية الحالية ، للعمل مع "الحقول" يعطي Bitrix أحداثًا معينة ، عند العمل مع "الخصائص" (وظائف "SetPropertyValues" و "SetPropertyValuesEx") ، لا يوجد حدث مع نوع العملية ، هناك حدث قبل وبعد المكالمة ، ولكنه لا من المعروف ما هي العملية التي يتم تنفيذها (إضافة / تحديث / حذف) ، وبالتالي يجب أيضًا نقل العملية من المعالج إلى المعالج.ربما لم أتمكن من معرفة ذلك ، وفي Bitrix يمكنك أن ترى القيم في وقت واحد كما هي وكيف ستكون ، أو ربما يجب تسجيل الحالة السابقة والحالة بعد ذلك بشكل منفصل ، ولكن لسبب ما قررت أن إدخال السجل يجب أن يكون بتنسيق "الخاصية ٪ name٪ كان٪ value قبل التغيير٪ => أصبح٪ value بعد٪ ”وبالتالي هناك الكثير من المشاكل في الحفاظ على الحالة العالمية.تحديد ما إذا كانت التغييرات مطلوبة
من الغريب ، ولكن سيتم استدعاء معالجنا لتغيير أي سجل لأي كتلة معلومات.لذلك ، في المعالج ، نحتاج إلى فهم سجل كتلة المعلومات التي تلقيناها في المعلمات.يتميز كتلة السجل بإحدى القيمتين: كتلة المعلومات نفسها ('IBLOCK_ID') وقسمها ('IBLOCK_SECTION_ID') ، وأحيانًا يكمن معرف القسم في مجموعة القيم مع الفهرس "IBLOCK_SECTION_ID" ، وأحيانًا "IBLOCK_SECTION" ، لذلك أقرأ معرف القسم من خلال كلا المفتاحين بأولوية "IBLOCK_SECTION".علاوة على ذلك ، في بعض الحالات ، لا يمكن تحديد معرف القسم من حيث المبدأ ، وبالتالي ، يجب أن يتم التحقق من الحاجة إلى إضافة إدخال إلى سجل التدقيق فقط على أساس معرف كتلة المعلومات.بعد تحديد كتلة المعلومات والقسم ، نقرر ضرورة تسجيل الحدث في المجلة.حفظ الحالة قبل التغييرات
يتكون كل إدخال كتلة غير مؤلفة من جزأين ، جزء واحد هو "الحقول" ، ويتم تغيير هذه المعلمات بالطرق:- CIBlockElement :: إضافة ()
- CIBlockElement :: تحديث ()
- CIBlockElement :: حذف ()
الجزء الآخر هو طرق "الخصائص":- CIBlockElement :: SetPropertyValues ()
- CIBlockElement :: SetPropertyValuesEx ()
لا أتذكر السبب ، ولكن من الأفضل الامتناع عن استخدام CIBlockElement :: SetPropertyValuesEx () في الكود الخاص بي.كل جزء من البيانات في معالج الأحداث الخاص به منفصل عن الآخر ، وبالتالي ، بالنقر فوق الزر "حفظ" ، يمكن إنشاء إدخالين في سجل التدقيق.تختلف تواقيع أحداث "الحقول" و "الخصائص" ، في الجزء الذي يتم فيه معالجة "الحقول" ، نحفظ الحالة الحالية للحقول ونعين القيمة للعملية ، وفي الجزء الذي يتم فيه معالجة "الخصائص" ، نحفظ الخصائص وأسمائها.نقوم بذلك بالطبع في معالج "قبل".تغيير التسجيل
في معالج "بعد" ، نكتب إلى السجل.عند تجميع قائمة الاختلافات في السجلات ، هناك مشكلة في السمات التي يمكن أن تأخذ قيمًا متعددة. يختلف تنسيق تسجيل الحالة "قبل" والحالة "بعد" لدرجة أنه لا يمكن لأحدهما استنتاج الآخر ، لذلك عند تحديد ما إذا كان سيتم تسجيل التغييرات ، ستستنتج دائمًا أن التسجيل ضروري.كود المصدر للتدقيق في المستودع في ملف src / Topliner / Scheme / Logger.php .إضافة علامة تبويب مخصصة إلى بطاقة infoblock (في مصنف Bitrix)
لإضافة بطاقة ، يتم استخدام نهج مشابه للتدقيق - نضيف معالج:AddEventHandler('main', 'OnAdminIBlockElementEdit',
Array(PermitTab::class, 'OnInit'));
في طريقة OnInit ، نحدد الطرق الأخرى للعمل مع علامة التبويب في محرر Bitrix:class PermitTab
{
const LINKS = 'links';
function OnInit($arArgs)
{
$permits = BitrixScheme::getPermits();
$pubPermits = BitrixScheme::getPublishedPermits();
$blockId = (int)$arArgs['IBLOCK']['ID'];
$letShow = $blockId === $permits->getBlock()
|| $blockId === $pubPermits->getBlock();
$result = false;
if ($letShow) {
$result = [
'TABSET' => 'LinksToConstructs',
'GetTabs' => [static::class, 'GetTabs'],
'ShowTab' => [static::class, 'ShowTab'],
'Action' => [static::class, 'Action'],
'Check' => [static::class, 'Check'],
];
}
return $result;
}
}
أولاً ، بالطبع ، نتحقق من أنه بالنسبة لكتلة المعلومات هذه ، نحتاج إلى إظهار علامة تبويب المستخدم الخاصة بنا ، إذا لزم الأمر ، نقوم بتعيين الطرق.لا يوجد شيء خاص لإخباره هنا ، راجع المصادر في مستودع src / Topliner / Scheme / PermitTab.php ، اقرأ الوثائق.قدوة لتفويض إجراءات المستخدم
تعمل أساليب Bitrix للتفويض مع مقياس خطي للحقوق ، أي سيناريو حيث يمكن أن يكون الأول والثاني ، ولكن ليس الثالث ، والآخر يمكن أن يكون الثاني والثالث ، ولكن ليس الأول ، لا يمكنك تنفيذ Bitrix مباشرة.بالنسبة لمثل هذه السيناريوهات الصعبة في Bitrix ، هناك ببساطة فحص لبعض الإذن ، وفي الكود عند تنفيذ العملية ، ترى ما إذا كان المستخدم لديه إذن أم لا ، وتسمح بالدورين الأول والثاني ، ويسمح الدوران الثاني والثالث بالدور الآخر. $constSec = BitrixScheme::getConstructs();
$isAllow = CIBlockSectionRights::UserHasRightTo(
$constSec->getBlock(), $constSec->getSection(),
BitrixPermission::ELEMENT_ADD, false);
if (!$isAllow) {
$output['message'] = 'Forbidden, not enough permission;';
}
- $ constSec-> getBlock () - معرف كتلة المعلومات
- $ constSec-> getSection () - معرف القسم
- BitrixPermission :: ELEMENT_ADD - رمز الإذن
في المصنف (دليل كتلة المعلومات) في كتل المعلومات والأقسام الضرورية ، تقوم بتعيين الحقوق المناسبة للأدوار. وزع الأدوار على المستخدمين وسيكون كل شيء تحت سيطرتك.المصادقة
إذا كنت بحاجة إلى مصادقة المستخدم لبعض الصفحات ، فما عليك سوى إضافة:<?php
define("NEED_AUTH", true);
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php");
?>
<?php
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/footer.php");
?>
عند تحميل مثل هذه الصفحة ، سيعطي Bitrix نموذج تسجيل دخول إذا لم يقم المستخدم بتسجيل الدخول بعد.إذا كنت تحتاج فقط إلى توصيل Bitrix في نوع من البرنامج النصي ، فعندئذٍ:require_once($_SERVER['DOCUMENT_ROOT']
. '/bitrix/modules/main/include/prolog_before.php');
العمل مع الدلائل
تسمى الدلائل "الجديدة" (اعتبارًا من نوفمبر 2019) في Bitrix "HighloadBlock" ، والعمل معها غير قياسي إلى حد ما.يمكن تخزين كل كتلة Hyload في جدول منفصل ، لذلك ، للوصول إلى الدليل ، يجب عليك في كل مرة تحديد اسم الجدول لقراءته. لكي لا تفعل ذلك باستمرار ، في Bitrix تحتاج إلى إنشاء مثيل لفئة للوصول إلى البيانات. يتم إنشاء مثيل في سطرين:CModule::IncludeModule('highloadblock');
$entity = HighloadBlockTable::compileEntity('ConstructionTypes');
$reference = $entity->getDataClass();
حيث "ConstructionTypes" هو الرمز المرجعي. لكيلا تكتب هذين السطرين باستمرار ، يمكنك كتابة فصل سينشئ لنا أمثلة مرجعية ( src / Topliner / Bitrix / BitrixReference.php ).بعد ذلك ، نعمل مع المثيل كما هو الحال مع فئة Bitrix ORM المعتادة (D7):
$data = $reference::getList(array(
'select' => array('UF_NAME', 'UF_XML_ID'),
'filter' => array('UF_TYPE_ID' => 0)
));
مستودع (بعناية ، ولصق الكثير من النسخ)شكرا لاهتمامكم.