Jump to content

دليل:دوال المحلل اللغوي

From mediawiki.org
This page is a translated version of the page Manual:Parser functions and the translation is 100% complete.
MediaWiki extensions

إن دوال المحلل اللغوي التي أضيفت في نسخة ميدياويكي 1.7 هي أحد أنواع الامتدادات التي تندمج اندماجا وثيقا مع المحلل اللغوي. يجب ألا تخلط بين عبارة «دوال المحلل اللغوي – parser functions» وبين Extension:ParserFunctions ، التي هي عبارة عن مجموعة من دوال المحلل اللغوي البسيطة. (اذهب إلى Help:Extension:ParserFunctions كي تطالع تلك).

الوصف

منذ أن امتداد الوسم متوقع منه أن يتناول نص غير معالج ويرد نص إتش تي إم إل إلى المتصفح، يمكن لدالة معرب لغوي ’التفاعل‘ مع عناصر الويكي الأخرى في الصفحة. يمكن على سبيل المثال استخدام مخرجات دوال المعرب اللغوي في صفة متغير في قالب أو في توليد وصلة شبكية.

البنية اللغوية المعتادة لدالة معرب لغوي هي كما يلي:

{{ #functionname: param1 | param2 | param3 }}

لمزيد من المعلومات، طالع التوثيق المخصص لمتغير ‎Parser::setFunctionHook ( $id, $callback, $flags = 0 )‎. تذكر أعمال التوثيق هذه ما يلي:

يجب أن تكون صيغة دالة الاستدعاء كما يلي:
function myParserFunction( $parser, $arg1, $arg2, $arg3 ) { ... }
أو باستخدام SFH_OBJECT_ARGS:
function myParserFunction( $parser, $frame, $args ) { ... }

المتغير الأول للاستدعاء يمرر كافة الطلبات في صيغة نص صرف. الثاني يمرر كافة الطلبات في صفة سطر PPNode ، عدا الأول ($args[0])، وهو نص في الوقت الراهن، رغم أن هذا الأمر قد يتغير في المستقبل. تمثّل هذه نص الويكي غير الموسّع. يمكن استخدام المعلم $frame في توسيع هذه السعات حسب الحاجة. يستخدم هذا عادة في المعالجة المشروطة حتى يجري تقييم الحالة true لا غير باستخدام دوال المعرب اللغوي من نوع if- أو switch-like. يمكن أيضًا لعنصر الإطار الارتقاء في هيكل الوثيقة للحصول على معلومات عن المستدعي وتسخير دوال لتحديد عمق الاستدعاء والوقت المستغرق وما إذا كانت نتائج دوال المعرب اللغوي متغيّرة أم لا وكذلك التعامل مع هذه الأمور.

إن استحداث دالة معرب لغوي معقد قليلًا مقارنة باستحداث وسم جديد لأن اسم الدالة يتعين أن يكون كلمة سحرية، كملة مفتاحية تساند الأسماء المستعارة وأعمال الأقلمة.

مثال بسيط

ما يلي هو مثال على امتداد ينشئ دالة معرب لغوي.

يذهب التسجيل في ملف extension.json ويذهب الكود البرمجي في ملف src/ExampleExtensionHooks.php على الترتيب:

Standard: Using the HookHandler interface:
extension.json
{
	"name": "ExampleExtension",
	"author": "Me",
	"version": "1.0.0",
	"url": "https://www.mediawiki.org/wiki/Extension:ExampleExtension",
	"descriptionmsg": "exampleextension-desc",
	"license-name": "GPL-2.0-or-later",
	"type": "parserhook",
	"MessagesDirs": {
		"ExampleExtension": [
			"i18n"
		]
	},
	"AutoloadClasses": {
		"ExampleExtensionHooks": "src/ExampleExtensionHooks.php"
	},
	"ExtensionMessagesFiles": {
		"ExampleExtensionMagic": "ExampleExtension.i18n.php"
	},
	"Hooks": {
		"ParserFirstCallInit": "ExampleExtensionHooks::onParserFirstCallInit"
	},
	"manifest_version": 1
}
{
	"name": "ExampleExtension",
	"author": "Me",
	"version": "1.0.0",
	"url": "https://www.mediawiki.org/wiki/Extension:ExampleExtension",
	"descriptionmsg": "exampleextension-desc",
	"license-name": "GPL-2.0-or-later",
	"type": "parserhook",
	"MessagesDirs": {
		"ExampleExtension": [
			"i18n"
		]
	},
	"AutoloadClasses": {
		"ExampleExtensionHooks": "src/ExampleExtensionHooks.php"
	},
	"ExtensionMessagesFiles": {
		"ExampleExtensionMagic": "ExampleExtension.i18n.php"
	},
	"Hooks": {
		"ParserFirstCallInit": "onParserFirstCallInit"
	},
	"HookHandlers": {
		"ExampleExtensionHooks": {
			"class": "MediaWiki\\Extension\\ExampleExtension\\Hooks"
		}
	},
	"manifest_version": 1
}
ExampleExtensionHooks.php
<?php

class ExampleExtensionHooks {

   // تسجيل أي حالات استدعاء عرض مستخدما المعرب اللغوي
   public static function onParserFirstCallInit( Parser $parser ) {
      // يستحدث رابط دالة يربط بين الكلمة المفتاحية  وبين renderExample()
      $parser->setFunctionHook( 'example', [ self::class, 'renderExample' ] );
   }

   // يعرض مخرجات {{#example:}}.
   public static function renderExample( Parser $parser, $param1 = '', $param2 = '', $param3 = '' ) {
      // مدخلات المتغيرات هي نصوص ويكي توسع فيها القوالب.
      // يجب أن تكون المخرجات هي نصوص ويكي أيضًا.
      $output = "param1 is $param1 and param2 is $param2 and param3 is $param3";

      return $output;
   }

}
<?php

class ExampleExtensionHooks implements ParserFirstCallInitHook {

   // Register any render callbacks with the parser
   public function onParserFirstCallInit( $parser ) {
      // Create a function hook associating the <code>example</code> magic word with renderExample()
      $parser->setFunctionHook( 'example', [ $this, 'renderExample' ] );
   }

   // Render the output of {{#example:}}.
   public function renderExample( $parser, $param1 = '', $param2 = '', $param3 = '' ) {
      // The input parameters are wikitext with templates expanded.
      // The output should be wikitext too.
      $output = "param1 is $param1 and param2 is $param2 and param3 is $param3";
      return $output;
   }

}

يجب أن يحتوي ملف آخر يحمل الاسم ExampleExtension.i18n.php في مجلد الامتدادات لديك (لا في المجلد الفرعي src/) على ما يلي:

<?php
/**
 * @license GPL-2.0-or-later
 * @author اسمك (YourUserName)
 */

$magicWords = [];

/** English
 * @author اسمك (YourUserName)
 */
$magicWords['en'] = [
   'example' => [ 0, 'example' ],
];

حينما يكون هذا الامتداد مفعلًا،

  • {{#example: hello | hi | hey}}

ينتج عنه:

  • param1 هو hello وparam2 هو hi وparam3 هو hey
إن متوالية magicWords هذه ليست اختيارية. لو محيت، لن تعمل دوال المعرب اللغوي بكل بساطة؛ سوف يعرض {{#example: hello | hi}} كما لو كان الامتداد غير مثبت. لو كانت مصفوفة اللغة المحددة قد بدأت لا مصفوفة الكلمات السحرية ذاتها، يمكن أن ينتج عن هذا أخطاء في الأقلمة منذ أن الترجمات من امتدادات أخرى تتسرب إلى ترجماتك. يمكنك ربط الكلمات السحرية في السطر في بي إتش بي بدلا من استخدام ملف تدويل. هذا الأمر مفيد حينما تعرّف الروابط في ملف LocalSettings.php
MediaWiki\MediaWikiServices::getInstance()->getContentLanguage()->mMagicExtensions['wikicodeToHtml'] = ['MAG_CUSTOM', 'custom'];

داخل ملف LocalSettings.php

يمكن تحديد الكلمات سحرية ودوال المعرب اللغوي التي تتعامل معها كاملة في LocalSettings.php.

$wgHooks['ParserFirstCallInit'][] = function ( Parser $parser ) 
{
	MediaWiki\MediaWikiServices::getInstance()->getContentLanguage()->mMagicExtensions['wikicodeToHtml'] = ['wikicodeToHtml', 'wikicodeToHtml'];

	$parser->setFunctionHook( 'wikicodeToHtml', 'wikicodeToHtml' );
};
 
function wikicodeToHtml( Parser $parser, $code = '' ) 
{
	$title = $parser->getTitle();
	$options = $parser->Options();
	$options->enableLimitReport(false);
	$parser = $parser->getFreshParser();
	return [$parser->parse($code, $title, $options)->getText(), 'isHTML' => true];
}

دوال أطول

في حالات الدوال الطويلة، ربما ترغب في تقسيم دوال الربط إلى ملف _body.php أو .hooks.php وجعلها دوال ثابتة تحت فئة واحدة. يمكنك من ثمّ تحميل الفئة مستخدمًا ‎$wgAutoloadClasses واستدعاء الدوال الثابتة في الروابط؛ مثل:

ضع ما يلي في ملف ‎extension.json لديك:

"Hooks": {
	"ParserFirstCallInit": "ExampleExtensionHooks::onParserFirstCallInit"
},
"AutoloadClasses": {
	"ExampleExtensionHooks": "src/ExampleExtensionHooks.php"
}

ثم ضع ما يلي في ملف ‎src/ExampleExtensionHooks.php لديك:

class ExampleExtensionHooks {
      public static function onParserFirstCallInit( Parser $parser ) {
           $parser->setFunctionHook( 'example', [ self::class, 'renderExample' ] );
      }
}


واجهة المعرب اللغوي

التحكم في الإعراب اللغوي للمخرجات

إن أردت أن تُعرَب نصوص الويكي التي تُرجِعها دوال المعرب اللغوي إعرابًا برمجيًا كاملًا (يشمل ذلك توسيع القوالب)، اضبط قيمة خيار noparse لتصبح false أثناء الرجوع:

return [ $output, 'noparse' => false ];

يبدو أن القيمة الافتراضية لخيار noparse تغيرت من false إلى true، على الأقل في بعض الحالات، في وقت ما قريب من الإصدار 1.12.

بالعكس، كي تجعل دوال المعرب اللغوي لديك ترد نص إتش تي إم إل يظل دون إعراب برمجي، بدلا من رده في صيغة نصوص ويكي، استخدم التالي:

return [ $output, 'noparse' => true, 'isHTML' => true ];

التسمية

تضيف برمجيات ميدياويكي بصفة افتراضية محرف «هاش» (علامة الرقم، #) إلى اسم كل دالة من دوال المعرب اللغوي. كي توقف هذه الإضافة (والحصول على دوال معرب لغوي لا يضاف إليها البادئة #)، أضف الثابت ‎SFH_NO_HASH‎ في وسيطة flags الاختيارية إلى setFunctionHook، كما هو مبين فيما يلي.

حينما تختار اسم لا يحتوي على البادئة «هاش»، لاحظ أن ضم صفحة تحمل اسم يبدأ باسم تلك الدالة يتبعه علامة النقطتين لن يصبح ممكنًا. تجنب على وجه التحديد أسماء الدوال التي تساوي اسم نطاق اسم. في حالة أن ضم [١] بين مواقع الويكي مفعّل، تجنب أيضًا أسماء الدوال التي تساوي بادئة وصل بين مواقع الويكي.

الرابط setFunctionHook

لمزيد من التفاصيل عن الواجهة في المعرب اللغوي، طالع توثيق رابط setFunctionHook في ملف includes/Parser.php. إليك نسخة (يحتمل أن تكون متقادمة) من تلك التعليقات:

دالة setFunctionHook( $id, $callback, $flags = 0 )

معلمات:

  • ‎$id النص – معرف الكلمة السحرية
  • ‎$callback مختلط – دالة الاستدعاء (والعنصر) المطلوب استخدامها
  • ‎$flags الأعداد الصحيحة – اختياري. القيم:
  • SFH_NO_HASH (1) ثابت لو كنت تستعدي الدالة دون استخدام #.
  • SFH_OBJECT_ARGS (2) لو كنت تمرر عنصر PPFrame وسلسلة من الحجج بدلًا من مجموعة من حجج الدالة، ولهذا الغرض طالع السالف.
  • القيمة الافتراضية تصبح 0 (لا وسوم).

القيمة المردودة: دالة الاستدعاء القديمة لهذا الاسم، في حال وجودها

صغ دالة، مثل، ‎{{#sum:1|2|3}}‎. يجب أن تكون دالة الاستدعاء على الشكل التالي:

function myParserFunction( $parser, $arg1, $arg2, $arg3 ) { ... }

يجوز أن يرد الاستدعاء إما النتيجة النصية للدالة أو متوالية يوجد النص فيها في العنصر «0» وعدد من الوسوم في العناصر الأخرى. تحدد أسماء الوسوم في المفاتيح. الوسوم الصالحة كما يلي:

الاسم النوع القيمة الافتراضية بيان
found منطقية/بوليانية true true لو كان النص المردود صالح ويتعين وقف معالجة القالب.
text ? ? النص المردود من السمة. لو كانت isChildObj أو isLocalObj محددة، ينبغي أن يكون هذا عنقود DOM بدلا من ذلك.
noparse منطقية/بوليانية true true لو كان النص يجب ألا يعالج مسبقًا في شجرة DOM، مثال وسوم إتش تي إم إل غير الآمنة يجب ألا تنزع وخلافه.
isHTML منطقية/بوليانية ? true لو كان النص المردود هو نص إتش تي إم إل ويتعين حمايته من التحويل إلى نصوص ويكي. ولكن طالع النقاش
nowiki منطقية/بوليانية عادةً false true لو كان يجب تخطي ترميز الويكي الموجود في القيمة المردودة (نص).
isChildObj منطقية/بوليانية ? true لو كان النص هو عنقود DOM يحتاج للتوسيع في إطار تابع.
isLocalObj منطقية/بوليانية ? true لو كان النص هو عنقود DOM يحتاج للتوسيع في الإطار الحالي. تعتمد القيمة الافتراضية على قيم ونواتج أخرى.
preprocessFlags ? false وسوم PPFrame الاختيارية الواجب استخدامها حينما تعرب النص المردود برمجيًا. ينطبق هذا حينما يكون noparse هو false لا غير.
title ? false عنصر Title حيث أخذ النص.
forceRawInterwiki منطقية/بوليانية ? true لو كان إجبار حالات الدمج بين مواقع الويكي يتعين أن يجري في الوضع الخام، لا في وضع يعرض النتيجة النهائية.

دوال المحلل اللغوي التي تتطلب موارد ضخمة

بعض دوال المعرب اللغوي تشكّل استخدامًا ضخمًا لموارد موقع الويكي ويجب أن توسم بوسم «مجهدة - expensive». ينحصر عدد دوال المعرب اللغوي المجهدة على أي صفحة كانت باستخدام الإعداد $wgExpensiveParserFunctionLimit . يرجع الحكم على ما يعتبر مجهدًا أم لا للدالة نفسها، إلا أن الأمر عادة، هو أن أي شيء يحتمل أن ينتج عنه تأخير يتخطى مدة التعامل البسيط مع البيانات يجب أن يكون محل نظر. يشتمل هذا على أمور مثل قراءة قواعد البيانات وكتابتها أو تدشين نص قشرة برمجي متزامنًا أو التعامل مع الملفات. على الناحية الأخرى، لا يتطلب الأمر بالضرورة أن توسم كل هذه الدوال. على سبيل المثال، تسم برمجيات سيمانتك ميدياويكي نسبة من حالات قراءة قواعد البيانات بوسم مجهدة. هذا الأمر بسبب أنه في صفحات كثيرة البيانات، يجوز بسهولة أن تتخطى الحدود القصوى لدوال المحلل اللغوي المجهدة المعتادة. في مثل تلك الحالات، يصبح احتمال بطء الأداء الملحوظ الذي لا يوسم بوسم مجهد هو مقايضة مقبولة للتمتع بما تقدمه وظائف برمجيات سيمانتك ميدياويكي.

إن أردت وسم دالة معرب لغوي بوسم مجهدة، من داخل متن الكود البرمجي للدالة، استخدم $result = $parser->incrementExpensiveFunctionCount();. سوف تكون القيمة المردودة هي false لو وصل الحد الأقصى للدالة المجهدة أو جرى تخطيه.

متغيرات تحمل اسم

لا تدعم دوال المعرب اللغوي المتغيرات التي تحمل أسماء بذات الطريقة التي تدعمها القوالب وامتدادات الوسوم، إلا أنه من المفيد أحيانًا اختلاقها. يعتاد غالبًا المستخدمين على استخدام الشريط العمودي ( | ) في أغراض فصل الوسيطات، لذا من الجيد أن يكون هذا ممكنًا في سياق دوال المعرب اللغوي أيضًا. إليك مثال بسيط على كيفية تحقيق هذا الأمر:

function ExampleExtensionRenderParserFunction( &$parser ) {
	// لنقترض أن المستخدم استدعى دالة المعرب اللغوي كما يلي:
	// {{#myparserfunction: foo=bar | apple=orange | banana }}

	$options = extractOptions( array_slice( func_get_args(), 1 ) );

	// الآن لديك سلسلة تشبه التالي:
	// [foo] => 'bar'
	// [apple] => 'orange'
	// [banana] => true
	// واصل كتابة كودك البرمجي...
}

/**
 * يحوّل سلسلة من القيم بالصيغة [0] => "name=value"
 * إلى سلسلة ربطية فعلية بالصيغة [name] => value
 * لو كان no = غير موجود، سيفترض أن القيمة صحيح مشابهة لما يلي: [name] => true
 *
 * @param array string $options
 * @return array $results
 */
function extractOptions( array $options ) {
	$results = [];
	foreach ( $options as $option ) {
		$pair = array_map( 'trim', explode( '=', $option, 2 ) );
		if ( count( $pair ) === 2 ) {
			$results[ $pair[0] ] = $pair[1];
		}
		if ( count( $pair ) === 1 ) {
			$results[ $pair[0] ] = true;
		}
	}
	return $results;
}

انظر أيضا

إرشادات عمومية ومتعلقة:

الكود:

أمثلة: