From 0ef8a4de0b0b3897513cf4d6fb7e2ae4448a1c63 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 11 Oct 2024 16:13:36 -0400 Subject: [PATCH] Add new $pages->saveFields([ 'field1', 'field2', 'etc.' ]); method that enables you to save multiple fields on a page. Previously you could only save the entire page, or 1 field at a time. --- wire/core/Pages.php | 36 +++++++++++++++-- wire/core/PagesEditor.php | 84 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/wire/core/Pages.php b/wire/core/Pages.php index d5e54764..a4068e8a 100644 --- a/wire/core/Pages.php +++ b/wire/core/Pages.php @@ -39,8 +39,9 @@ * HOOKABLE METHODS * ================ * @method PageArray find($selectorString, array $options = array()) Find and return all pages matching the given selector string. Returns a PageArray. #pw-group-retrieval - * @method bool save(Page $page, $options = array()) Save any changes made to the given $page. Same as : $page->save() Returns true on success. #pw-group-manipulation + * @method bool save(Page $page, $options = array()) Save any changes made to the given $page. Same as $page->save(); Returns true on success. #pw-group-manipulation * @method bool saveField(Page $page, $field, array $options = array()) Save just the named field from $page. Same as: $page->save('field') #pw-group-manipulation + * @method array saveFields(Page $page, $fields, array $options = array()) Saved multiple named fields for $page. @since 3.0.242 #pw-group-manipulation * @method bool trash(Page $page, $save = true) Move a page to the trash. If you have already set the parent to somewhere in the trash, then this method won't attempt to set it again. #pw-group-manipulation * @method bool restore(Page $page, $save = true) Restore a trashed page to its original location. #pw-group-manipulation * @method int|array emptyTrash(array $options = array()) Empty the trash and return number of pages deleted. #pw-group-manipulation @@ -90,9 +91,6 @@ * @method savedPageOrField(Page $page, array $changes) Hook inclusive of both saved() and savedField(). * @method found(PageArray $pages, array $details) Hook called at the end of a $pages->find(). * - * TO-DO - * ===== - * @todo Update saveField to accept array of field names as an option. * */ @@ -870,6 +868,36 @@ class Pages extends Wire { return $this->editor()->saveField($page, $field, $options); } + /** + * Save multiple named fields from given page + * + * ~~~~~ + * // you can specify field names as array… + * $a = $pages->saveFields($page, [ 'title', 'body', 'summary' ]); + * + * // …or a CSV string of field names: + * $a = $pages->saveFields($page, 'title, body, summary'); + * + * // return value is array of saved field/property names + * print_r($a); // outputs: array( 'title', 'body', 'summary' ) + * ~~~~~ + * + * @param Page $page Page to save + * @param array|string|string[]|Field[] $fields Array of field names to save or CSV/space separated field names to save. + * These should only be Field names and not native page property names. + * @param array|string $options Optionally specify one or more of the following to modify default behavior: + * - `quiet` (boolean): Specify true to bypass updating of modified user and time (default=false). + * - `noHooks` (boolean): Prevent before/after save hooks (default=false), please also use $pages->___saveField() for call. + * - See $options argument for Pages::save() for additional options + * @return array Array of saved field names (may also include property names if they were modified) + * @throws WireException + * @since 3.0.242 + * + */ + public function ___saveFields(Page $page, $fields, array $options = array()) { + return $this->editor()->saveFields($page, $fields, $options); + } + /** * Add a new page using the given template and parent * diff --git a/wire/core/PagesEditor.php b/wire/core/PagesEditor.php index 7bece01d..d924fc44 100644 --- a/wire/core/PagesEditor.php +++ b/wire/core/PagesEditor.php @@ -937,6 +937,90 @@ class PagesEditor extends Wire { return $return; } + /** + * Save multiple named fields from given page + * + * ~~~~~ + * // you can specify field names as array… + * $a = $pages->saveFields($page, [ 'title', 'body', 'summary' ]); + * + * // …or a CSV string of field names: + * $a = $pages->saveFields($page, 'title, body, summary'); + * + * // return value is array of saved field/property names + * print_r($a); // outputs: array( 'title', 'body', 'summary' ) + * ~~~~~ + * + * @param Page $page Page to save + * @param array|string|string[]|Field[] $fields Array of field names to save or CSV/space separated field names to save. + * These should only be Field names and not native page property names. + * @param array|string $options Optionally specify one or more of the following to modify default behavior: + * - `quiet` (boolean): Specify true to bypass updating of modified user and time (default=false). + * - `noHooks` (boolean): Prevent before/after save hooks (default=false), please also use $pages->___saveField() for call. + * - See $options argument for Pages::save() for additional options + * @return array Array of saved field names (may also include property names if they were modified) + * @throws WireException + * @since 3.0.242 + * + */ + public function saveFields(Page $page, $fields, array $options = array()) { + + $saved = array(); + $quiet = !empty($options['quiet']); + $noHooks = !empty($options['noHooks']); + + // do not update modified user/time until last save + if(!$quiet) $options['quiet'] = true; + + if(!is_array($fields)) { + $fields = explode(' ', str_replace(',', ' ', "$fields")); + } + + foreach($fields as $key => $field) { + $field = trim("$field"); + if(empty($field) || !$page->hasField($field)) unset($fields[$key]); + } + + // save each field + foreach($fields as $field) { + if($noHooks) { + $success = $this->saveField($page, $field, $options); + } else { + $success = $this->pages->saveField($page, $field, $options); + } + if($success) { + $saved[$field] = $field; + $page->untrackChange($field); + } + } + + if($quiet) { + // do not save native properties or update page modified-user/modified + + } else { + // finish by saving the page without fields + $options['quiet'] = false; + + foreach($page->getChanges() as $name) { + if($page->hasField($name)) continue; + // add only changed native properties to saved list + $saved[$name] = $name; + } + + $options['noFields'] = true; + + if($noHooks) { + $this->save($page, $options); + } else { + $this->pages->save($page, $options); + } + } + + $this->pages->debugLog('saveFields', "$page:" . implode(',', $fields), $saved); + + return $saved; + } + /** * Silently add status flag to a Page and save *