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

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 كي تطالع تلك).

الوصف

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

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

{{ #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 في توسيع هذه السعات حسب الحاجة. يستخدم هذا عادة في المعالجة المشروطة حتى يجري تقييم الحالة «الصحيحة» لا غير باستخدام دوال المعرب اللغوي من نوع if-‎ أو switch-‎. يمكن أيضًا لعنصر الإطار الارتقاء في هيكل الوثيقة للحصول على معلومات عن المستدعي وتسخير دوال لتحديد عمق الاستدعاء والوقت المستغرق وما إذا كانت نتائج دوال المعرب اللغوي متغيّرة أم لا وكذلك التعامل مع هذه الأمور.

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

مثال بسيط

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

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

{
	"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
}
<?php
class ExampleExtensionHooks {
   // تسجيل أي حالات استدعاء عرض مستخدما المعرب اللغوي
   public static function onParserFirstCallInit( Parser $parser ) {

      // يستحدث رابط دالة يربط بين الكلمة المفتاحية «example» وبين ‎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;
   }
}

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

<?php
/**
 * @license GPL-2.0-or-later
 * @author Your Name (YourUserName)
 */

$magicWords = [];

/** English
 * @author Your Name (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‎ في وسيطة الوسوم الاختيارية إلى setFunctionHook، كما هو مبين فيما يلي.

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

الرابط setFunctionHook

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

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

معلمات:

  • ‎$id النص – معرف الكلمة السحرية
  • ‎$callback مختلط – دالة الاستدعاء (والعنصر) المطلوب استخدامها
  • ‎$flags الأعداد الصحيحة – اختياري، ضبطت قيمته لتكون ثابت ‎SFH_NO_HASH‎ كي تستدعي الدالة دون استخدام «#».

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

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

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

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

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

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

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

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

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

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

function ExampleExtensionRenderParserFunction( &$parser ) {
	// Suppose the user invoked the parser function like so:
	// {{#myparserfunction: foo=bar | apple=orange | banana }}

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

	// Now you've got an array that looks like this:
	// [foo] => 'bar'
	// [apple] => 'orange'
	// [banana] => true
	// Continue writing your code...
}

/**
 * Converts an array of values in form [0] => "name=value"
 * into a real associative array in form [name] => value
 * If no = is provided, true is assumed like this: [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;
}

انظر أيضا

General and related guides:

Code:

Examples: