סטטוס וטיוטות

איך סוג תוכן מקבל סטטוס ושמירת טיוטה, מה האתר מציג, איך עוקפים את הסינון בקוד שלכם, ואיך מסכי הניהול מדברים עם content_status ועם CONTENT_WORKFLOW.

⏱ 16 דק' קריאה 2887 מילים

סוג תוכן שהפעיל workflow מקבל שלושה דברים: סטטוס לכל רשומה (טיוטה, ממתין לאישור, מתוזמן, מפורסם, מוסתר), טיוטה נפרדת לשינוי ברשומה שכבר באוויר, וסינון אוטומטי בצד האתר, כך שמבקר לא רואה דבר שלא פורסם. הכול מנוהל במחלקה CONTENT_WORKFLOW, ומסכי הניהול מדברים איתה דרך ה-API של content_status. הפיצ'ר זמין מגרסת הליבה 5.0.148 (בדקו ב-system/core/version.txt), ותזמון ותצוגה מקדימה נוספו עליו מגרסה 5.0.155 (תזמון ותצוגה מקדימה).

בעמוד הזה system/ הוא תיקיית הליבה הפרוסה (api/core בקוד המקור), ו-{admin} הוא CONFIG::$admin_url של האתר.

מה כבר קיים ומה בגרסה מאוחרת

כל צד השרת עובד: העמודות, הטיוטות, הסינון, התזמון ו-API. ברשימות panel_table יש לשוניות סטטוס וכפתורי פרסום והסתרה לשורות שנבחרו. מסכי הניהול המלאים (כפתורי "שמירה כטיוטה" ו"שליחה לאישור" בטופס, מסך הטיוטות והתזמון) יגיעו בגרסה מאוחרת יותר. עד אז אפשר לשלוח את הפעולות לטופס ישירות, כמו בסעיף "מה הטופס מקבל".

מי משתתף#

טבלה משתתפת רק כששלושת התנאים מתקיימים:

  1. היא רשומה כסוג תוכן עם workflow = 1, בקריאה CONTENT::register() שהפאנל שלה מבצע.
  2. יש בה העמודה wz_status.
  3. האתר לא כיבה את הפיצ'ר עם הפרמטר content_workflow שערכו "0" (ראו פרמטרים ושפות).

כל טבלה אחרת לא משתנה בכלום. כיום Pages (עמודי התוכן) היא הסוג הרשום, והיא נרשמת עם workflow => 1, עם preview_url => "pages/{id}" ועם title_field => "title".

טבלה משלכם

העמודות של CRM_pages מגיעות לאתר בעדכון גרסה (update_db מעתיק מבנה מהמאסטר). טבלה משלכם לא מקבלת אותן לבד. כדי להכניס אותה לתהליך, הוסיפו את העמודות בעצמכם (הגדרות ב"העמודות" למטה) ורשמו אותה עם CONTENT::register("my_table", ["label" => "...", "panel" => "MyPanel", "workflow" => 1, "preview_url" => "my/{id}", "title_field" => "title"]). ההרשמה כותבת ל-CRM_content_types רק כשמשהו השתנה, ולכן אפשר לקרוא לה בכל טעינה של הפאנל.

העמודות#

העמודות נוספות לטבלה הראשית של סוג התוכן (לא לטבלת ה-_content), כלומר סטטוס אחד לרשומה בכל השפות.

עמודהטיפוסברירת מחדלמשמעות
wz_statusvarchar(12)'published'draft, review, scheduled, published או hidden
wz_publish_atdatetimeNULLמתי רשומה מתוזמנת עולה לאוויר
wz_unpublish_atdatetimeNULLמתי רשומה מפורסמת מפסיקה להופיע באתר
wz_published_atdatetimeNULLהפעם הראשונה שהרשומה פורסמה
wz_created_byint0מזהה המנהל שיצר את הרשומה

לטבלה יש גם אינדקס על (wz_status, wz_publish_at). ברירת המחדל published היא כל התאימות לאחור: שורה שהייתה קיימת לפני העמודות, ושורה שקוד של אתר מכניס בלי להכיר אותן, נשארת גלויה.

להוספה ידנית לטבלה משלכם:

ALTER TABLE `CRM_my_table`
  ADD COLUMN `wz_status` varchar(12) NOT NULL DEFAULT 'published',
  ADD COLUMN `wz_publish_at` datetime NULL DEFAULT NULL,
  ADD COLUMN `wz_unpublish_at` datetime NULL DEFAULT NULL,
  ADD COLUMN `wz_published_at` datetime NULL DEFAULT NULL,
  ADD COLUMN `wz_created_by` int NOT NULL DEFAULT 0,
  ADD INDEX `wz_status_publish` (`wz_status`, `wz_publish_at`);

הסטטוסים#

ערךתווית בניהולהאתר מציג?
draftטיוטהלא
reviewממתין לאישורלא
scheduledמתוזמןלא, עד wz_publish_at
publishedמפורסםכן, כל עוד wz_unpublish_at ריק או בעתיד
hiddenמוסתרלא

רשומה מפורסמת ש-wz_unpublish_at שלה עבר לא מוצגת באתר גם לפני שהמתזמן הספיק לסמן אותה כ-hidden (ראו תזמון ותצוגה מקדימה). הרשימות בניהול מסמנות אותה כ"פג תוקף".

הקבועים CONTENT_WORKFLOW::STATUSES ו-CONTENT_WORKFLOW::LABELS מחזיקים את הרשימה ואת התוויות, ו-CONTENT_WORKFLOW::ACTIONS ממפה את פעולת הטופס לסטטוס.

מי רשאי לעבור בין סטטוסים#

מעברהרשאה
draft ל-review ובחזרהedit על הפאנל של סוג התוכן
כל מעבר אחר (פרסום, הסתרה, תזמון, פרסום מחדש)publish על הפאנל

הרשאת publish נבדקת כאפשרות נוספת של הפאנל (extra_perms ב-CRM_adminPanel_panels). פאנל שלא הגדיר אותה, דורש edit גם לפרסום. ראו הרשאות וקבוצות. הבדיקה עצמה היא CONTENT_WORKFLOW::can_publish(), והפונקציה CONTENT_WORKFLOW::needs($from, $to) אומרת איזו הרשאה מעבר דורש.

טיוטה של רשומה שכבר באוויר#

רשומה חדשה שעוד לא פורסמה היא פשוט שורה עם wz_status = 'draft'. הטבלה CRM_content_drafts נועדה רק לשינוי שממתין על רשומה שפורסמה (או הוסתרה): עד שמפרסמים, הגרסה שבאתר לא משתנה.

עמודהמשמעות
idמזהה הטיוטה
tbl, row_id, lang_idהטבלה (בלי CRM_), הרשומה והשפה. שלישייה ייחודית: טיוטה פתוחה אחת לרשומה בכל שפה
post_dataה-POST המלא של הטופס, כ-JSON, ועוד הפאנל והמתודה ששמרו. זה מה שהפרסום מריץ מחדש
overlayהעמודות שהטיוטה הייתה כותבת (main ו-content), מה שהתצוגה המקדימה מציגה
base_version_idהגרסה בהיסטוריה שהטיוטה נפתחה ממנה, להתראה על התנגשות (ראו גרסאות תוכן)
statusdraft, review או scheduled
publish_atמתי להעלות את הטיוטה, כשהיא מתוזמנת
admin_idהמנהל ששמר
updated_atמתי נשמרה לאחרונה

הטבלה נוצרת באתר בעדכון גרסה. אתר שעוד לא קיבל אותה ממשיך לשמור כמו קודם (CONTENT_WORKFLOW::ready() מחזיר false).

למה שומרים POST ולא ערכים#

קלט בטופס יכול לעשות יותר מלכתוב עמודה: SEO, גלריות, תגיות, קישורים בין רשומות. הטיוטה לא מריצה את זה. היא שומרת את ה-POST, ובפרסום הליבה מזינה אותו שוב לאותו פאנל ולאותו טופס, ממש כמו שמירה רגילה. לכן כל קלט עושה בדיוק מה שהיה עושה בשמירה חיה, והגרסה שנרשמת בהיסטוריה היא מסוג publish. אותה שיטה משמשת את ה-MCP ואת ייבוא ה-Excel (POST מתוכנת לטופס).

מה הטופס מקבל#

הטופס מצהיר מה הוא רוצה בשדה POST בשם wz_action:

wz_actionמשמעות
draftשמירה כטיוטה
reviewשליחה לאישור
scheduleתזמון (דורש גם wz_publish_at, תאריך ושעה)
publishפרסום, שמירה חיה

התנהגות לפי המצב של הרשומה:

המצבמה קורה
רשומה חדשה, בלי wz_actionמי שמורשה לפרסם: נשמרת כ-published, כמו לפני שהפיצ'ר היה קיים. מי שלא מורשה: נשמרת כ-review (ראו למטה)
רשומה חדשה עם wz_actionנשמרת בסטטוס שהפעולה מבקשת (טיוטה, ממתין, מתוזמן או מפורסם)
רשומה שבאוויר (published או hidden) עם draft, review או scheduleהשורה החיה לא נוגעת. ה-POST נשמר ב-CRM_content_drafts
רשומה שבאוויר עם publish, או בלי wz_action ממי שמורשה לפרסםשמירה חיה רגילה
רשומה שלא באוויר (draft, review, scheduled)נשמרת במקום, והפעולה מזיזה את הסטטוס

publish ו-schedule דורשים הרשאת פרסום. בלי ההרשאה השמירה נדחית עם הודעה ולא נכתב דבר. schedule בלי תאריך תקף נדחה גם הוא.

שמירה בלי wz_action ממי שלא מורשה לפרסם (מגרסה 5.0.167) לא מעלה כלום לאוויר: הליבה מתייחסת אליה כאילו נשלח review, הפעולה שכפתור השמירה של הטופס נותן למנהל כזה. רשומה חדשה נשמרת כ-review, שינוי ברשומה שבאוויר נשמר כטיוטה שממתינה לאישור, ורשומה שעוד לא באוויר עוברת ל-review (גם רשומה מתוזמנת, כך ששינוי שלא אושר לא עולה במועד). שמירה אוטומטית של רשומה חדשה נשמרת כ-draft. טופס פשוט מוסיף להודעת השמירה שורה שאומרת שהרשומה נשלחה לאישור ולא פורסמה, ושמירה מתוכנתת מקבלת את המצב בכותרת AI-Record-Status. מי שמורשה לפרסם שומר בלי wz_action בדיוק כמו קודם.

שמירה אוטומטית. בקשת שמירה עם autosave=1 על רשומה שבאוויר הולכת תמיד לטיוטה, גם בלי wz_action, כך שהקלדה באמצע עריכה לא משנה את האתר. שמירה אוטומטית של רשומה שעוד לא באוויר נשמרת במקום.

שמירה חיה מנקה את הטיוטה של עצמה. שמירה חיה (לא אוטומטית) של רשומה, מאותו מנהל שיש לו עליה טיוטה, מוחקת את הטיוטה, כי היא כבר לא מתארת את מה שהמנהל התכוון.

קבצים. קובץ שהועלה ישירות ב-$_FILES לא ממתין בטיוטה, כי הקובץ הזמני נעלם בסוף הבקשה. שמירת טיוטה עם קובץ כזה נדחית עם הסבר. קלטים ששולחים מזהה של קובץ שכבר הועלה למאגר (כמו wzdrive) עובדים.

בשמירה מתוכנתת (כותרת AI-Form-Insert, כמו ב-MCP), שמירת טיוטה מחזירה את הכותרות AI-Draft-ID ו-AI-Draft-Status, ושמירה שנכתבה לרשומה עצמה מחזירה את AI-Record-Status עם הסטטוס שלה אחרי השמירה. save_record של ה-MCP מחזיר בהתאם mode: "draft" עם draft_id ו-draft_status, או status לצד id.

פרסום טיוטה#

CONTENT_WORKFLOW::publish_draft() מריצה מחדש את ה-POST השמור דרך הפאנל, כשמירה חיה, ואז מוחקת את הטיוטה, מעבירה את הרשומה ל-published ומנקה את המטמון של העמוד. אם אדם אחר שמר את הרשומה החיה אחרי שהטיוטה נפתחה, הפרסום נעצר עם conflict ופרטי ההתנגשות, אלא אם ביקשתם force.

מה האתר מציג: הסינון#

כשהקוד רץ מחוץ לניהול (CONFIG::$system_type שונה מ-admin), כל שאילתה של DB::query על טבלה משתתפת מקבלת את התנאי הבא על הטבלה הראשית (הכינוי tConf בשאילתה שהליבה בונה):

tConf.wz_status = 'published'
AND (tConf.wz_unpublish_at IS NULL OR tConf.wz_unpublish_at > '<now>')

ה-<now> הוא השעון של PHP (date()), אותו שעון שבו המנהל הקליד את התאריכים, ולא NOW() של שרת מסד נתונים שאולי יושב באזור זמן אחר.

המשמעות לכם כמפתחי אתר:

  • מסוננות: DB::query(...), וכל מה שנשען עליו: ->get_row(), ->get_all(), ->num_rows() ו-DB::get_val(). בקר pages רגיל, שקורא DB::get_val("pages", $id), מקבל false על טיוטה ומחזיר 404, בלי שינוי שורה בקוד האתר. ראו שאילתות.
  • לא מסוננות: SQL גולמי (DB::get_all("SELECT ..."), DB::get_row, DB::sql), וטבלאות שמצורפות ב-filter של שאילתה. אתר שמשתמש ב-SQL גולמי על טבלת תוכן חייב להוסיף את התנאי בעצמו.
  • הניהול לא מסונן: בפאנלים אתם רואים הכול.
  • אתר שלא אימץ סטטוס לא מרגיש שינוי: כל השורות הקיימות הן published, ולכן הן ממשיכות להופיע.

SQL גולמי: CONTENT::visible_where()#

CONTENT::visible_where(string $table): string

מחזירה את תנאי "מה שהאתר מציג" לטבלה, בלי WHERE. לטבלה שאינה סוג תוכן עם סטטוס, או לאתר שכיבה את הפיצ'ר, היא מחזירה "1=1", כך שאפשר לקרוא לה בלי לבדוק. התנאי כתוב בלי כינוי טבלה, ולכן בשאילתה עם כמה טבלאות ודאו שהוא חל על הטבלה הנכונה.

$rows = DB::get_all("SELECT id FROM CRM_pages WHERE " . CONTENT::visible_where("pages") . " ORDER BY id DESC");

לעקוף את הסינון#

קוד שחייב לראות את כל הסטטוסים (כלי תחזוקה, משימת cron, דוח) בוחר באחת משתי דרכים.

לשאילתה אחת:

$q = DB::query("pages", ["id" => $id]);
$q->workflow_filter = false;
$row = $q->get_row(); // כולל טיוטות

לקטע קוד שלם:

CONTENT_WORKFLOW::$bypass = true;
try {
    $all = DB::query("pages", [], "id DESC")->get_all();
} finally {
    CONTENT_WORKFLOW::$bypass = false;
}
עקיפה היא לקוד שלכם בלבד

אל תעקפו את הסינון בקוד שמייצר תוכן לציבור (תבנית, בקר של עמוד, פיד, מפת אתר). טיוטה שדלפה לשם היא תוכן שלא אושר, באתר פתוח למנועי חיפוש. צריך לראות טיוטה באתר? זו תצוגה מקדימה, ראו תזמון ותצוגה מקדימה.

ה-API של content_status#

מסכי הניהול מדברים עם מודול ניהול בשם content_status, בכתובת {admin}/content_status/<method>?pmode=empg. הוא מחזיר JSON, ופתוח למנהל מחובר בלבד. הצפייה דורשת גישה לפאנל של סוג התוכן (השדה panel ב-CRM_content_types). מתודות POST דורשות גם טוקן CSRF: מביאים אותו ב-csrf, ושולחים גוף JSON עם השדה csrf (או את הכותרת X-WZ-CSRF). ראו CSRF, XSS ו-SQLi.

כשל תמיד נראה כך: {"success": false, "error": "<code>"}.

מתודהפרמטריםמחזירה
indexready, רשימת הסטטוסים והתוויות
countstblכמה רשומות בכל סטטוס, ועוד expired, with_draft, total
recordtbl, id, lang?עמודות wz_* של הרשומה, הטיוטה הפתוחה שלה, ומה המנהל הנוכחי רשאי (can.edit, can.publish)
draftstbl, ids (מופרדים בפסיק), lang?{row_id: סטטוס טיוטה} לעמוד שלם של רשימה
draftidטיוטה אחת עם ה-overlay שלה
pendinglimit?מה שממתין לאדם, ראו CONTENT_WORKFLOW::pending()
csrfהטוקן לבקשות POST
set (POST)tbl, ids[], status, publish_at?, unpublish_at?changed, skipped, refused, counts
publish_draft (POST)draft_id, force?תוצאת publish_draft()
discard_draft (POST)draft_id{success, draft_id}
previewtbl, id, lang?קישור תצוגה מקדימה, ראו תזמון ותצוגה מקדימה
share (POST)tbl, id, lang?קישור שיתוף, שם
scheduleמתי המתזמן יבדוק שוב, שם

כמה כללים:

  • ב-set כל רשומה נבדקת לפי המעבר שלה: מעבר שדורש publish למנהל בלי הרשאה נרשם ב-refused עם forbidden, וההמשך ממשיך. עד 500 רשומות בבקשה.
  • שינוי תאריך על אותו סטטוס נחשב מעבר של publish.
  • status: "scheduled" דורש publish_at. unpublish_at ריק מנקה את התאריך.
  • discard_draft של טיוטה של מנהל אחר דורש הרשאת פרסום. את הטיוטה של עצמכם אפשר לזרוק עם edit.
  • טיוטה נקראת תמיד עם הטבלה והפאנל שלה, לעולם לא לפי מה שנשלח בבקשה.

קודי שגיאה נפוצים: missing_tbl, type_without_workflow (הטבלה אינה סוג תוכן עם סטטוס), forbidden, not_found, bad_status, missing_ids, too_many, no_draft, post_only, csrf, וב-publish_draft: conflict, save_failed (עם errors לפי שדה), draft_unreadable, record_missing.

// שינוי סטטוס של שתי רשומות, מתוך פאנל הניהול
const base = "{admin}/content_status/";
const c = await (await fetch(base + "csrf?pmode=empg", { credentials: "same-origin" })).json();
const res = await (await fetch(base + "set?pmode=empg", {
  method: "POST",
  credentials: "same-origin",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ tbl: "pages", ids: [12, 13], status: "hidden", csrf: c.csrf }),
})).json();

ה-MCP והסטטוס#

בכלי הרשימה של ה-MCP (list_rows) כל שורה בפאנל של סוג תוכן עם סטטוס מקבלת wz_status, status_label, ואם צריך publish_at, unpublish_at ו-has_draft, כדי שסוכן לא יחשוב שטיוטה עלתה לאוויר. ראו קטלוג כלי ה-MCP.

ריפרנס: CONTENT_WORKFLOW#

המחלקה נמצאת ב-system/collections/CONTENT_WORKFLOW.php. שיטותיה לא זורקות חריגה: הן עונות, ובכשל רושמות שורה ל-error_log. השיטות של המתזמן מתוארות בתזמון ותצוגה מקדימה.

מאפיינים סטטיים#

שםברירת מחדלמשמעות
CONTENT_WORKFLOW::$bypassfalsetrue: שאילתות מחוץ לניהול רואות את כל הסטטוסים
CONTENT_WORKFLOW::$replayingfalsetrue בזמן שפרסום טיוטה מריץ מחדש את ה-POST: הטופס שומר חי, בלי טיוטה ובלי שינוי סטטוס
CONTENT_WORKFLOW::$last_savenullתוצאת שמירת הטופס האחרונה בבקשה: ok, table, id, errors

CONTENT_WORKFLOW::ready()#

public static function ready(): bool

האם הטבלה CRM_content_drafts קיימת באתר.

CONTENT_WORKFLOW::enabled()#

public static function enabled($table): bool

האם הטבלה משתתפת (שלושת התנאים שבראש העמוד). מקבלת שם עם או בלי CRM_, ושומרת תשובה לבקשה.

CONTENT_WORKFLOW::type()#

public static function type($table): ?array

שורת CRM_content_types של טבלה משתתפת, או null.

CONTENT_WORKFLOW::query_filter()#

public static function query_filter($table): string

התנאי שמתווסף ל-DB::query. מחזירה מחרוזת ריקה בניהול, כש-$bypass דלוק, או לטבלה שאינה משתתפת. בתצוגה מקדימה תקפה היא פותחת גם את הרשומה אחת של התצוגה. את הפונקציה מפעילה הליבה, לא קוד אתר.

CONTENT_WORKFLOW::can_publish() ו-can_edit()#

public static function can_publish($table): bool
public static function can_edit($table): bool

האם המנהל הנוכחי רשאי לפרסם או לערוך את סוג התוכן. false כשאין פאנל לסוג.

CONTENT_WORKFLOW::needs()#

public static function needs($from, $to): ?string

ההרשאה שמעבר סטטוס דורש: "edit" בין draft ל-review, "publish" לכל מעבר אחר, null כשהסטטוס זהה או שאינו סטטוס.

CONTENT_WORKFLOW::record()#

public static function record($table, $id): ?array

עמודות wz_* של רשומה (id, wz_status, wz_publish_at, wz_unpublish_at, wz_published_at, wz_created_by), או null.

CONTENT_WORKFLOW::set_status()#

public static function set_status($table, $ids, $to, $opts = []): array

משנה סטטוס של רשומות. ההרשאות באחריות הקורא (ה-API בודק אותן עם needs()).

פרמטרמשמעות
$idsמזהה או מערך מזהים
$toאחד הסטטוסים
$opts["publish_at"]חובה כש-$to הוא scheduled
$opts["unpublish_at"]תאריך הסתרה, מחרוזת ריקה מנקה אותו
$opts["source"]מקור השינוי לאירוע (ברירת מחדל api)

מחזירה ["success" => true, "changed" => [ids], "skipped" => [id => סיבה]], או ["success" => false, "error" => ...] (not_workflow, bad_status, publish_at_required). פרסום ידני של רשומה שתאריך ההסתרה שלה כבר עבר מנקה את התאריך, כדי שלא תוסתר מיד. כל שינוי שולח אירוע status (אירועי תוכן) ומנקה את מטמון העמוד.

$res = CONTENT_WORKFLOW::set_status("pages", [12, 13], "scheduled", ["publish_at" => "2026-11-01 08:00:00"]);

CONTENT_WORKFLOW::counts()#

public static function counts($table): array

{draft, review, scheduled, published, hidden, expired, with_draft, total}. expired הוא רשומות מפורסמות שתאריך ההסתרה שלהן עבר, ו-with_draft הוא רשומות שיש להן טיוטה פתוחה.

CONTENT_WORKFLOW::pending()#

public static function pending($limit = 30): array

מה שממתין לאדם, מכל סוגי התוכן שהמנהל רשאי לראות: רשומות וטיוטות בסטטוס review או scheduled, מתוזמנות לפי התאריך ואחריהן ממתינות לפי החדשות. כל פריט: tbl, label, panel, row_id, lang_id, title, status, publish_at, kind (record או draft), draft_id, admin_id, updated_at. המקסימום 200.

CONTENT_WORKFLOW::draft(), draft_by_id() ו-draft_ids()#

public static function draft($table, $id, $lang): ?array
public static function draft_by_id($draft_id): ?array
public static function draft_ids($table, $ids, $lang = null): array

הראשונה מחזירה את הטיוטה של רשומה בשפה (עם post_data ו-overlay מפוענחים), השנייה לפי המזהה של הטיוטה. draft_ids מחזירה [row_id => סטטוס] לכמה רשומות בשאילתה אחת, למשל לסימון "יש שינויים שלא פורסמו" בעמוד של רשימה.

CONTENT_WORKFLOW::discard_draft()#

public static function discard_draft($draft_id): bool

זורקת טיוטה. לא נוגעת ברשומה החיה.

CONTENT_WORKFLOW::publish_draft()#

public static function publish_draft($draft_id, $opts = []): array

מפרסמת טיוטה כמתואר למעלה. $opts["force"] מפרסם גם מעל שמירה חיה חדשה יותר. מחזירה ["success" => true, "tbl", "row_id", "lang_id", "version"], או ["success" => false, "error" => ...] עם אחד מהקודים no_draft, not_workflow, record_missing, draft_unreadable, conflict (עם conflict), save_failed (עם errors).

CONTENT_WORKFLOW::form_draft(), form_columns() ו-form_result()#

public static function form_draft($form): ?string
public static function form_columns($form, $qu): void
public static function form_result($form, $ok): void

שלוש נקודות החיבור של Form לתהליך: לפני שמירה (להסיט לטיוטה או לדחות), רגע לפני ה-INSERT או ה-UPDATE (לקבוע את עמודות wz_*), ואחרי שמירה (לתעד את התוצאה ולנקות מטמון). הליבה מפעילה אותן, ופאנל לא אמור לקרוא להן.

התיעוד נכתב מתוך הקוד של ליבה 5.0.185.