<?php
/**
* Dependencies API: WP_Dependencies base class
*
* @since 2.6.0
*
* @package WordPress
* @subpackage Dependencies
*/
/**
* Core base class extended to register items.
*
* @since 2.6.0
*
* @see _WP_Dependency
*/
#[AllowDynamicProperties]
class WP_Dependencies {
/**
* An array of all registered dependencies keyed by handle.
*
* @since 2.6.8
*
* @var _WP_Dependency[]
*/
public $registered = array();
/**
* An array of handles of queued dependencies.
*
* @since 2.6.8
*
* @var string[]
*/
public $queue = array();
/**
* An array of handles of dependencies to queue.
*
* @since 2.6.0
*
* @var string[]
*/
public $to_do = array();
/**
* An array of handles of dependencies already queued.
*
* @since 2.6.0
*
* @var string[]
*/
public $done = array();
/**
* An array of additional arguments passed when a handle is registered.
*
* Arguments are appended to the item query string.
*
* @since 2.6.0
*
* @var array
*/
public $args = array();
/**
* An array of dependency groups to enqueue.
*
* Each entry is keyed by handle and represents the integer group level or boolean
* false if the handle has no group.
*
* @since 2.8.0
*
* @var (int|false)[]
*/
public $groups = array();
/**
* A handle group to enqueue.
*
* @since 2.8.0
*
* @deprecated 4.5.0
* @var int
*/
public $group = 0;
/**
* Cached lookup array of flattened queued items and dependencies.
*
* @since 5.4.0
*
* @var array
*/
private $all_queued_deps;
/**
* List of assets enqueued before details were registered.
*
* @since 5.9.0
*
* @var array
*/
private $queued_before_register = array();
/**
* Processes the items and dependencies.
*
* Processes the items passed to it or the queue, and their dependencies.
*
* @since 2.6.0
* @since 2.8.0 Added the `$group` parameter.
*
* @param string|string[]|false $handles Optional. Items to be processed: queue (false),
* single item (string), or multiple items (array of strings).
* Default false.
* @param int|false $group Optional. Group level: level (int), no group (false).
* @return string[] Array of handles of items that have been processed.
*/
public function do_items( $handles = false, $group = false ) {
/*
* If nothing is passed, print the queue. If a string is passed,
* print that item. If an array is passed, print those items.
*/
$handles = false === $handles ? $this->queue : (array) $handles;
$this->all_deps( $handles );
foreach ( $this->to_do as $key => $handle ) {
if ( ! in_array( $handle, $this->done, true ) && isset( $this->registered[ $handle ] ) ) {
/*
* Attempt to process the item. If successful,
* add the handle to the done array.
*
* Unset the item from the to_do array.
*/
if ( $this->do_item( $handle, $group ) ) {
$this->done[] = $handle;
}
unset( $this->to_do[ $key ] );
}
}
return $this->done;
}
/**
* Processes a dependency.
*
* @since 2.6.0
* @since 5.5.0 Added the `$group` parameter.
*
* @param string $handle Name of the item. Should be unique.
* @param int|false $group Optional. Group level: level (int), no group (false).
* Default false.
* @return bool True on success, false if not set.
*/
public function do_item( $handle, $group = false ) {
return isset( $this->registered[ $handle ] );
}
/**
* Determines dependencies.
*
* Recursively builds an array of items to process taking
* dependencies into account. Does NOT catch infinite loops.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
* @since 2.8.0 Added the `$group` parameter.
*
* @param string|string[] $handles Item handle (string) or item handles (array of strings).
* @param bool $recursion Optional. Internal flag that function is calling itself.
* Default false.
* @param int|false $group Optional. Group level: level (int), no group (false).
* Default false.
* @return bool True on success, false on failure.
*/
public function all_deps( $handles, $recursion = false, $group = false ) {
$handles = (array) $handles;
if ( ! $handles ) {
return false;
}
foreach ( $handles as $handle ) {
$handle_parts = explode( '?', $handle );
$handle = $handle_parts[0];
$queued = in_array( $handle, $this->to_do, true );
if ( in_array( $handle, $this->done, true ) ) { // Already done.
continue;
}
$moved = $this->set_group( $handle, $recursion, $group );
$new_group = $this->groups[ $handle ];
if ( $queued && ! $moved ) { // Already queued and in the right group.
continue;
}
$keep_going = true;
if ( ! isset( $this->registered[ $handle ] ) ) {
$keep_going = false; // Item doesn't exist.
} elseif ( $this->registered[ $handle ]->deps && array_diff( $this->registered[ $handle ]->deps, array_keys( $this->registered ) ) ) {
$keep_going = false; // Item requires dependencies that don't exist.
} elseif ( $this->registered[ $handle ]->deps && ! $this->all_deps( $this->registered[ $handle ]->deps, true, $new_group ) ) {
$keep_going = false; // Item requires dependencies that don't exist.
}
if ( ! $keep_going ) { // Either item or its dependencies don't exist.
if ( $recursion ) {
return false; // Abort this branch.
} else {
continue; // We're at the top level. Move on to the next one.
}
}
if ( $queued ) { // Already grabbed it and its dependencies.
continue;
}
if ( isset( $handle_parts[1] ) ) {
$this->args[ $handle ] = $handle_parts[1];
}
$this->to_do[] = $handle;
}
return true;
}
/**
* Register an item.
*
* Registers the item if no item of that name already exists.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string $handle Name of the item. Should be unique.
* @param string|false $src Full URL of the item, or path of the item relative
* to the WordPress root directory. If source is set to false,
* the item is an alias of other items it depends on.
* @param string[] $deps Optional. An array of registered item handles this item depends on.
* Default empty array.
* @param string|bool|null $ver Optional. String specifying item version number, if it has one,
* which is added to the URL as a query string for cache busting purposes.
* If version is set to false, a version number is automatically added
* equal to current installed WordPress version.
* If set to null, no version is added.
* @param mixed $args Optional. Custom property of the item. NOT the class property $args.
* Examples: $media, $in_footer.
* @return bool Whether the item has been registered. True on success, false on failure.
*/
public function add( $handle, $src, $deps = array(), $ver = false, $args = null ) {
if ( isset( $this->registered[ $handle ] ) ) {
return false;
}
$this->registered[ $handle ] = new _WP_Dependency( $handle, $src, $deps, $ver, $args );
// If the item was enqueued before the details were registered, enqueue it now.
if ( array_key_exists( $handle, $this->queued_before_register ) ) {
if ( ! is_null( $this->queued_before_register[ $handle ] ) ) {
$this->enqueue( $handle . '?' . $this->queued_before_register[ $handle ] );
} else {
$this->enqueue( $handle );
}
unset( $this->queued_before_register[ $handle ] );
}
return true;
}
/**
* Add extra item data.
*
* Adds data to a registered item.
*
* @since 2.6.0
*
* @param string $handle Name of the item. Should be unique.
* @param string $key The data key.
* @param mixed $value The data value.
* @return bool True on success, false on failure.
*/
public function add_data( $handle, $key, $value ) {
if ( ! isset( $this->registered[ $handle ] ) ) {
return false;
}
return $this->registered[ $handle ]->add_data( $key, $value );
}
/**
* Get extra item data.
*
* Gets data associated with a registered item.
*
* @since 3.3.0
*
* @param string $handle Name of the item. Should be unique.
* @param string $key The data key.
* @return mixed Extra item data (string), false otherwise.
*/
public function get_data( $handle, $key ) {
if ( ! isset( $this->registered[ $handle ] ) ) {
return false;
}
if ( ! isset( $this->registered[ $handle ]->extra[ $key ] ) ) {
return false;
}
return $this->registered[ $handle ]->extra[ $key ];
}
/**
* Un-register an item or items.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string|string[] $handles Item handle (string) or item handles (array of strings).
*/
public function remove( $handles ) {
foreach ( (array) $handles as $handle ) {
unset( $this->registered[ $handle ] );
}
}
/**
* Queue an item or items.
*
* Decodes handles and arguments, then queues handles and stores
* arguments in the class property $args. For example in extending
* classes, $args is appended to the item url as a query string.
* Note $args is NOT the $args property of items in the $registered array.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string|string[] $handles Item handle (string) or item handles (array of strings).
*/
public function enqueue( $handles ) {
foreach ( (array) $handles as $handle ) {
$handle = explode( '?', $handle );
if ( ! in_array( $handle[0], $this->queue, true ) && isset( $this->registered[ $handle[0] ] ) ) {
$this->queue[] = $handle[0];
// Reset all dependencies so they must be recalculated in recurse_deps().
$this->all_queued_deps = null;
if ( isset( $handle[1] ) ) {
$this->args[ $handle[0] ] = $handle[1];
}
} elseif ( ! isset( $this->registered[ $handle[0] ] ) ) {
$this->queued_before_register[ $handle[0] ] = null; // $args
if ( isset( $handle[1] ) ) {
$this->queued_before_register[ $handle[0] ] = $handle[1];
}
}
}
}
/**
* Dequeue an item or items.
*
* Decodes handles and arguments, then dequeues handles
* and removes arguments from the class property $args.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string|string[] $handles Item handle (string) or item handles (array of strings).
*/
public function dequeue( $handles ) {
foreach ( (array) $handles as $handle ) {
$handle = explode( '?', $handle );
$key = array_search( $handle[0], $this->queue, true );
if ( false !== $key ) {
// Reset all dependencies so they must be recalculated in recurse_deps().
$this->all_queued_deps = null;
unset( $this->queue[ $key ] );
unset( $this->args[ $handle[0] ] );
} elseif ( array_key_exists( $handle[0], $this->queued_before_register ) ) {
unset( $this->queued_before_register[ $handle[0] ] );
}
}
}
/**
* Recursively search the passed dependency tree for a handle.
*
* @since 4.0.0
*
* @param string[] $queue An array of queued _WP_Dependency handles.
* @param string $handle Name of the item. Should be unique.
* @return bool Whether the handle is found after recursively searching the dependency tree.
*/
protected function recurse_deps( $queue, $handle ) {
if ( isset( $this->all_queued_deps ) ) {
return isset( $this->all_queued_deps[ $handle ] );
}
$all_deps = array_fill_keys( $queue, true );
$queues = array();
$done = array();
while ( $queue ) {
foreach ( $queue as $queued ) {
if ( ! isset( $done[ $queued ] ) && isset( $this->registered[ $queued ] ) ) {
$deps = $this->registered[ $queued ]->deps;
if ( $deps ) {
$all_deps += array_fill_keys( $deps, true );
array_push( $queues, $deps );
}
$done[ $queued ] = true;
}
}
$queue = array_pop( $queues );
}
$this->all_queued_deps = $all_deps;
return isset( $this->all_queued_deps[ $handle ] );
}
/**
* Query the list for an item.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string $handle Name of the item. Should be unique.
* @param string $status Optional. Status of the item to query. Default 'registered'.
* @return bool|_WP_Dependency Found, or object Item data.
*/
public function query( $handle, $status = 'registered' ) {
switch ( $status ) {
case 'registered':
case 'scripts': // Back compat.
if ( isset( $this->registered[ $handle ] ) ) {
return $this->registered[ $handle ];
}
return false;
case 'enqueued':
case 'queue': // Back compat.
if ( in_array( $handle, $this->queue, true ) ) {
return true;
}
return $this->recurse_deps( $this->queue, $handle );
case 'to_do':
case 'to_print': // Back compat.
return in_array( $handle, $this->to_do, true );
case 'done':
case 'printed': // Back compat.
return in_array( $handle, $this->done, true );
}
return false;
}
/**
* Set item group, unless already in a lower group.
*
* @since 2.8.0
*
* @param string $handle Name of the item. Should be unique.
* @param bool $recursion Internal flag that calling function was called recursively.
* @param int|false $group Group level: level (int), no group (false).
* @return bool Not already in the group or a lower group.
*/
public function set_group( $handle, $recursion, $group ) {
$group = (int) $group;
if ( isset( $this->groups[ $handle ] ) && $this->groups[ $handle ] <= $group ) {
return false;
}
$this->groups[ $handle ] = $group;
return true;
}
/**
* Get etag header for cache validation.
*
* @since 6.7.0
*
* @global string $wp_version The WordPress version string.
*
* @param string[] $load Array of script or style handles to load.
* @return string Etag header.
*/
public function get_etag( $load ) {
/*
* Note: wp_get_wp_version() is not used here, as this file can be included
* via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case
* wp-includes/functions.php is not loaded.
*/
global $wp_version;
$etag = "WP:{$wp_version};";
foreach ( $load as $handle ) {
if ( ! array_key_exists( $handle, $this->registered ) ) {
continue;
}
$ver = $this->registered[ $handle ]->ver ?? $wp_version;
$etag .= "{$handle}:{$ver};";
}
/*
* This is not intended to be cryptographically secure, just a fast way to get
* a fixed length string based on the script versions. As this file does not
* load the full WordPress environment, it is not possible to use the salted
* wp_hash() function.
*/
return 'W/"' . md5( $etag ) . '"';
}
}
! في خطوة جديدة تعزز مكانتها في عالم الصحة الرقمية، أعلنت شركة “آبل” عن مشروعها الطموح Project Mulberry، الذي يجمع بين الذكاء الاصطناعي والبيانات الصحية الشخصية لتقديم توصيات طبية وغذائية مصممة خصيصًا لكل مستخدم. المشروع يأتي كجزء من توسع آبل في مجالات الصحة والتغذية والعلاج الطبيعي. يهدف Project Mulberry إلى تحويل الهاتف الذكي إلى مساعد صحي افتراضي، يستند إلى معلومات دقيقة يتم جمعها من أجهزة مثل آيفون وآبل ووتش، لتقديم نصائح تتعلق بالنوم، التغذية، التمارين الرياضية، وحتى الوضعية الجسدية. يركز التطبيق على التكامل بين التحليل البيولوجي، والنصائح الشخصية، والمحتوى التعليمي المرئي. ويطمح إلى تقديم تجربة أكثر شمولاً… تبدأ من قياس عدد الخطوات، ولا تنتهي قبل تقديم خطة علاجية وتغذوية تراعي تفاصيل المستخدم. وقد استعانت آبل بفريق من الأطباء وخبراء التغذية والعلاج الطبيعي، لتدريب نموذجها الذكي وتحسين دقة التوصيات. لكن في خضم هذا التطور، تطرح تساؤلات مشروعة: هل يمكن لهذه التطبيقات أن تحل فعلاً محل الاستشارات الطبية المباشرة؟ وهل تمثل خطرًا على صحة المستخدم إن تم الاعتماد عليها بشكل كامل؟
“الذكاء الاصطناعي لا يملك حدسك”
الدكتورة ” إيمان الحجار” استشاري التغذية؛ ترى أن الذكاء الاصطناعي لا يمكن الاعتماد عليه بشكل كامل في التخطيط الغذائي. خلال تدريب الطلبة، لاحظت أن أدوات الذكاء الاصطناعي ترتكب أخطاء واضحة في حساب السعرات، وتعتمد على معلومات غير مكتملة أو غير دقيقة، فضلًا عن تجاهلها لعادات وثقافات المجتمعات، مثل اقتراح أطعمة غير مقبولة دينيًا أو باهظة الثمن لا تناسب جميع الفئات. ترى د. إيمان أن التغذية لا تقتصر على وضع خطة مكتوبة، بل تحتاج إلى تواصل إنساني مباشر مع المريض، لفهم حالته النفسية والسلوكية، إذ قد يخفي بعض العادات الغذائية الحقيقية أو يتظاهر باتباع نظام صحي. من خلال الملاحظة المباشرة ولغة الجسد، تستطيع كمتخصصة كشف مشاكل لا يمكن للتطبيقات رصدها. تؤكد أن بعض المرضى يختبرون الذكاء الاصطناعي، وأحيانًا حتى الأخصائيين أنفسهم، كما تختلف شخصيات المرضى بين النرجسية أو السلبية أو الإنكار، ما يجعل التعامل الإنساني المباشر ضرورة، خاصة في حالات الأكل العاطفي أو الاضطرابات السلوكية المرتبطة بالتغذية. رغم ذلك، ترى أن الذكاء الاصطناعي يمكن أن يكون مكملًا مفيدًا، لا بديلًا. فهي استخدمته مثلًا مع الطلبة مرضى السكري في تطبيق ترفيهي يساعدهم على التعرف إلى السعرات الحرارية بشكل ممتع. كما تسهم التطبيقات في دعم الأخصائيين من خلال الردود التلقائية أو المتابعة اليومية، لكن مع ضرورة أن يكون التحكم بيد الأخصائي، لا العكس. وتحذر من مخاطر التطبيقات غير الموثوقة التي قد تنتهك الخصوصية أو تستغل البيانات، مشددة على أهمية المتابعة الشخصية مع الطبيب، لما تحققه من تواصل وجداني وتأثير نفسي إيجابي، خصوصًا عند إشراك المرضى في أنشطة جماعية ومشاركة وجباتهم، مما يشعرهم بالانتماء والدعم، ويقلل من العزلة والانطوائية. وتختم بأن العامل البشري لا غنى عنه، لأن مجرد الحوار بين المريض والأخصائي يمثل علاجًا بحد ذاته، ووسيلة لفهم أعمق ونتائج أفضل
العلاج الطبيعي: دعم لا بديل
أما في مجال العلاج الطبيعي، فيؤكد د. محمود عادل، استشاري العلاج الطبيعي –، أن الذكاء الاصطناعي يتمتع بإمكانات ملحوظة في تقديم إرشادات مخصصة اعتمادًا على تحليل بيانات المستخدمين، لكن الإشراف المتخصص يظل ضروريًا لضمان السلامة والفعالية، خاصة أن السلامة تمثل أولوية قصوى. ويشدد على أن المريض لا يجب أن يخضع لأي تجربة علاجية دون توجيه من مختص. يرى أن الذكاء الاصطناعي يمكن أن يكون مساعدًا في حالات محددة بسيطة أو لأغراض وقائية، وقد يشبه جزئيًا بعض جوانب جلسات العلاج الطبيعي. ومع ذلك، لا يمتلك القدرة على الحلول محل عملية التقييم والعلاج الشاملة التي يقوم بها الأخصائي، لأهمية المتابعة الدقيقة لحالة المريض. ويشير إلى أن مشروعًا مثل “Project Mulberry” يمكن أن يكون عنصرًا داعمًا لجلسات العلاج الطبيعي، لكنه لا يغني عنها، بل يسهل عملية المتابعة بين الجلسات ويوفر الوقت للمعالج والمريض. أما عن المخاطر، فيحذر من الاعتماد الكلي على التوجيهات التقنية دون استشارة أخصائي، لما قد يسببه ذلك من أخطاء في التشخيص أو أداء تمارين غير مناسبة، وهو ما قد يؤدي إلى تفاقم الإصابة، خصوصًا في حالات العضلات أو العمود الفقري. ويتابع: حتى مع تزويد التطبيقات بصور إشعاعية، يصعب عليها تقييم ما قد يضر المريض، كما أن الفيديوهات والصور يمكن أن تساعد في شرح التمارين، لكنها لا تعوض التوجيه المباشر، خاصة في الحالات المعقدة التي تتطلب تعديلاً مستمرًا بحسب استجابة الجسم التدريب الرياضي: حماس لا يمكن برمجته
المدرب الرقمي في جيبك…،
تؤكد المدربة المعتمدة شيماء بركات أن الذكاء الاصطناعي، رغم تطوره، لا يمكن أن يحل محل المدرب البشري بأي شكل من الأشكال. وترى شيماء أن أنظمة الذكاء الاصطناعي قد تكون مفيدة في بعض الجوانب التقنية، خاصة عند توفر بيانات دقيقة وواضحة، لكنها لا تمتلك الفهم الكامل لاحتياجات كل مستخدم على حدة. كما أن الاعتماد على كاميرا الهاتف لتحليل الحركات لا يضاهي الملاحظة الفورية والخبرة العملية التي يتمتع بها المدرب، لا سيما أن تقييم الأداء البدني يتطلب قراءة دقيقة لتفاعل الجسم واستجابته أثناء التمرين. وتحذر من الاعتماد الكلي على هذه التطبيقات دون إشراف بشري مباشر، مشيرة إلى أن غياب العنصر الإنساني قد يؤدي إلى مشكلات عديدة، أبرزها الإصابة أو الفشل في تحقيق الأهداف، إضافة إلى شعور المتدرب بالملل أو فقدان الحافز بسبب غياب التشجيع والدعم اللحظي. كما تلفت إلى أن الذكاء الاصطناعي قد لا يكون قادرًا على التعامل مع الحالات الفردية الجديدة أو النادرة، وهو ما قد ينتج عنه عواقب سلبية عند غياب التقييم البشري المتخصص. وتختتم شيماء رأيها بالتأكيد على أن “التطبيقات الذكية ستظل أدوات مساعدة مفيدة، لكنها لا يمكن أن تحل محل التفاعل البشري الحي، أو تلغي الحاجة إلى خبرة المدرب الشخصي ومتابعته الدقيقة.” ميزة التطوير المستمر… ولكن! مشروع آبل مدعوم بفريق طبي يعمل على تدريب نموذج الذكاء الاصطناعي باستمرار، ما يعزز دقة التوصيات مع الوقت. كما أن إضافة خاصية متابعة التغذية وتحليل نمط النوم ومراقبة التمارين تجعل من التطبيق منصة شاملة. ومع ذلك، يبقى الاعتماد الكلي على الخوارزميات محل جدل. “ربما يكون المشروع مكملاً ممتازًا للرعاية الصحية، لكنه لا يجب أن يكون بديلاً عنها” ، يقول د. محمود. أداة مساعدة لا بديل مطلق: من الواضح أن الذكاء الاصطناعي بدأ يلعب دورًا متزايدًا في عالم الصحة. لكن حتى الآن، تظل قدراته محدودة أمام تعقيد الجسد البشري. التطبيقات الذكية قد تسهم في تحسين نمط الحياة، لكنها لا يمكن أن تحل محل المعرفة البشرية المتخصصة. في النهاية، الصحة تظل مسؤولية مشتركة بين الإنسان… والتقنية.