Repository navigation
Repair and protect Linked Orders' links and finish its port audit items - #30
Merged
Merged
Conversation
WooCommerce 11.3.0 is stable on wordpress.org, WP Packages and the stubs, while the root and every plugin still require and declare 11.2. Since the v2.0.0 tag falls after 11.3, the monorepo moves its floor with its locks (X374, A761). The root's and each plugin's locks take WooCommerce 11.3.0, each plugin's take its stubs 11.3.0 and phpstorm-stubs v2026.3. The constraints, each entry's WC requires at least and WC tested up to, the readmes' Installation and Upgrade Notice lines and the changelog fragments that name the floor read 11.3. Assisted-by: Claude Code:claude-opus-5-5
WooCommerce's wc_create_order() opens and saves the order an order_id names, and Linked Orders force-deletes whatever the creator returned when its link is refused, so a caller or filter naming the parent, or an order already linked, gets that order permanently deleted (A268). The row passes the parent's and a linked order's ids on every storage and expects a null return with _doing_it_wrong, both orders kept with their links and addresses, and no created-by meta. Assisted-by: Claude Code:claude-opus-5-5
dws_lowc_create_linked_child() wrote the parent's addresses onto whatever its creator returned and force-deleted it when the link was refused, so a creator that returned the parent or an order already in a tree, as wc_create_order() does for an order_id, lost that order for good (A268). The check that refuses an order of an unsupported type now also refuses the parent and an order with a parent or children, with its _doing_it_wrong and a null return, before the order is changed. The docblock names the residual X117 accepts: an existing order without links is still deleted when the link gives up on the lock. Assisted-by: Claude Code:claude-opus-5-5
WooCommerce catches what an order save throws, logs it and returns the order's id, so dws_lowc_link_orders() reported success after a child save that wrote nothing, leaving the parent listing a child that names no parent, which a second parent could then claim (A269). The rows make the child's save throw on every storage, through the linking API and through child creation, and expect false or the refusal error, the parent's children unsaved and the created child deleted. Assisted-by: Claude Code:claude-opus-5-5
A link saved the parent and then the child and reported success, though WooCommerce logs a save that fails and returns as if it had saved, so a failed child write left a permanent one-sided link (A269, X144). Inside the lock, the child now saves first and its parent is read back from the database with the order-tables data caching off, as the reads before it; when it does not name the parent the link returns false without saving the parent, so child creation deletes the child it made. The forced read moves into one helper both reads share. Assisted-by: Claude Code:claude-opus-5-5
v1 linked orders without refusing a cycle, and a site upgrading from it keeps those links, so dws_lowc_get_root_order() loops forever and dws_lowc_get_orders_tree() recurses until the request dies (A292). The row stores a two-order cycle on every storage and expects both walks to return; it counts the nodes the walk builds through the supported-types filter and throws past a thousand, so an endless walk fails the row instead of hanging the suite. Assisted-by: Claude Code:claude-opus-5-5
dws_lowc_get_root_order() and dws_lowc_get_orders_tree() trusted the stored links, so a cycle v1 stored hung the first and overflowed the second on every screen that shows the tree (A292, X207). The root walk tracks the orders it has passed and stops below a repeat, and the tree walk runs depth first from a stack, listing each order once in the same order as before. The link-cycles changelog line covers the stored loops too. Assisted-by: Claude Code:claude-opus-5-5
The children of a deleted order keep its id as their parent and their stored depth, so they read as their own roots on the tree walks but as children in the depth column, the depth filter and the maximum depth (A290). The row trashes then deletes a parent on every storage and expects the trashed parent to keep its children, then each child stored as a root and each grandchild's depth rewritten below it. Assisted-by: Claude Code:claude-opus-5-5
A deleted order's children kept its id as their parent and their stored depth, so the depth column, the depth filter and the maximum depth went on counting them as children of an order that no longer exists (A290, X207). OrderDeletion runs on woocommerce_before_delete_order, which both storages fire only for a deletion for good. Under the linking lock, each child that names the order as its parent is stored as a root and its descendants' depths are rewritten below it; a trashed order keeps its children. The lock's wait moves into one helper that linking shares. Assisted-by: Claude Code:claude-opus-5-5
A v1 site keeps the children of orders v1 deleted, which still name their parent and their depth, and the half links v1's lost-update race left, where a child names a parent that does not list it; nothing repairs either (A290, A291). The row stores both on every storage, as v1 did, and runs the second migration step's batches until none remain: the orphan becomes a root with its descendant one level below, the unlisted child joins its parent's children, and the walk's position is gone. The helper that stores v1's links moves to a trait both test classes use. Assisted-by: Claude Code:claude-opus-5-5
A site upgrading from v1 keeps the children of orders v1 deleted, which still name their parent and their depth, and the half links v1's lost-update race left, where a child names a parent that does not list it; the screens then disagree on where such an order stands, and a second parent can claim a half-linked child (A290, A291, X207). The second migration step implements BatchedMigrationStepInterface, so the runner's scheduled hook runs it. Each batch takes the next page of 50 orders that store a parent and, under the linking lock, stores an orphan as a root with its descendants' depths rewritten, or adds a child its parent does not list to the parent's children, reading each write back and throwing when it did not land. A repair keeps every order on its page, so the walk's position is a page number, deleted once the walk ends; a batch that cannot take the lock runs again. Assisted-by: Claude Code:claude-opus-5-5
can_create_child() checks the primitive edit_shop_orders, which a user who may edit only their own orders holds, so that user may create a child of an order WooCommerce would not let them open (A293). The row gives a subscriber edit_shop_orders and Linked Orders' own capability on every storage, expects no child of another user's order, then one once edit_others_shop_orders is granted. Assisted-by: Claude Code:claude-opus-5-5
can_create_child() asked for the primitive edit_shop_orders, so a user who may edit only their own orders could create a child of another user's order and copy its addresses (A293, X208). It now checks the order type's edit_post capability with the order's id, or manage_woocommerce, as WooCommerce does before it opens an order; Linked Orders' own capability and the v1 filter stay. Assisted-by: Claude Code:claude-opus-5-5
Each orders-list row loaded its parent and every child to decide on one action, so a page of linked orders loaded their whole trees, and a row whose related order was deleted lost the action (A294). Completing a tree completes each descendant, which fires the completion hook again, so every descendant walked and saved its own subtree once more (A295). The list row stores a dangling child and a deleted parent on every storage and expects the tree action with one node built per row. The completion row records the orders the filter sees and expects each once, with one note per descendant, while an unrelated tree a callback completes mid-pass still completes its child. Assisted-by: Claude Code:claude-opus-5-5
Every orders-list row loaded its parent and children to decide on its tree action, so a page loaded whole trees, and a row whose related order was deleted lost the action (A294). Completing an order completed each descendant, whose own completion walked and saved its subtree again (A295, X209). A row now offers its tree when its stored depth is above 0 or it stores child ids, loading no related order, so a dangling id opens a tree of one. Autocompletion keeps the ids of the orders a pass in progress covers and starts no nested pass for them, while an order a callback completes outside the pass still completes its descendants. Assisted-by: Claude Code:claude-opus-5-5
The meta box's order links and the orders list's customer and tree actions open a new tab without saying so, and the list's depth filter has no accessible name (A296, A466, X210, X376, X133). The meta box row expects core's "(opens in a new tab)" in a screen-reader span inside each link; the list rows expect it after the name in each new-tab action's title, which WooCommerce prints as the button's aria-label, and a screen-reader label for the depth filter named after the order type. The end-to-end spec runs axe over the meta box, the orders list's top navigation and the settings form. Assisted-by: Claude Code:claude-opus-5-5
The meta box's order links and the orders list's customer and tree actions open a new tab without saying so, and the depth filter's select has no accessible name, a WCAG 4.1.2 failure v1 shipped too (A296, A466, X210, X376, X133). Each meta box link carries core's "(opens in a new tab)" in a screen-reader span. WooCommerce escapes a row action's name and prints its title as the aria-label, so the two new-tab actions pass a title of the name and the cue, which also shows as their tooltip. A screen-reader label named after the order type precedes the filter, as core labels its date filter. Assisted-by: Claude Code:claude-opus-5-5
Linked Orders' notices and help leave the merchant guessing: a refusal never names the maximum depth that causes it, notices name an order by id where its number exists, the lock refusal and the creator fallback are lowercase fragments, the depth help counts levels unlike the list and hides in a tooltip, the uninstall consent does not say that the links between orders go, an active tree or guest filter is invisible, the tree view is reachable only from a hidden column, and order-type labels sit in title case mid-sentence (A297-A305, X211, X375). The rows expect each refusal to name its order by number and the depth limit by where it is set, the creator fallback as a sentence, the depth help and the consent beside their fields, a line per active tree or guest filter with a link that drops it, the meta box's "View all linked orders" link, sentence-case headings, and the generic "order" wherever a label stood mid-phrase. Assisted-by: Claude Code:claude-opus-5-5
Refusals never named the maximum depth that caused them, notices named an order by id, two messages were lowercase fragments, the depth help counted levels unlike the list from inside a tooltip, the uninstall consent hid that the links between orders go, the tree and guest filters stayed on with no sign, the tree view sat only behind a hidden column, and order-type labels sat in title case mid-sentence (A297-A305, X211, X375). dws_lowc_get_child_refusal() names the setting's place where an order is at the maximum depth and the order's number otherwise, for the child-creation notice and the meta box; the failure notice names the order by number. The lock refusal and the creator fallback are sentences, the labels carry their colons, the depth help is a description counting children below the order, and the consent says the links go and that it cannot be undone. Each active tree or guest filter prints a line with a link that drops it, and the meta box links to the order's tree through dws_lowc_get_list_url(), which the row actions share. Phrases say "order" where a type label sat mid-phrase, and the group headings are in sentence case. Assisted-by: Claude Code:claude-opus-5-5
The port read DWS_LOWC_DEBUG only as a strict true, renamed the actions WooCommerce fires around the two settings groups, dropped the section's value filter for an id no group maps, numbered a linked child after every v1 child-created listener, and joined v1 hook names without v1's byte stripping (A281, A283-A286, X205). The rows define the constant as 'yes' and 1 in a fresh request, count the group actions under v1's _start and _end ids, read two unmapped ids through the section filter, give a v1 listener at priority 20 the number to replace, and add control and high bytes to the hook-name parity rows. Assisted-by: Claude Code:claude-opus-5-5
DWS_LOWC_DEBUG needed a strict true, the settings groups lost the ids
whose actions v1 listeners hook, a section read of an unmapped id
skipped the section filter, Sequential Order Numbers Pro numbered a
child after every v1 child-created listener, and v1 hook names kept
control and high bytes (A281, A283-A286, X205).
The constant reads through FILTER_VALIDATE_BOOL; the groups' title and
end ids are dws-lowc_{group}_start and _end; a read without a group
passes the section filter for an id no group maps; numbering joins v1's
action at the default priority once WordPress reports that action
running, and leaves it after the v1 pass, since a callback removing its
own priority makes WordPress skip the next; the hook-name joiner strips
bytes below 32 and above 127 again. A changelog line records that the
integration no longer checks v1's 1.18 floor (A282).
Assisted-by: Claude Code:claude-opus-5-5
v1 added its Settings and Community support links under the settings and support keys, with the aria-labels "View settings" and "Visit community forums"; the port appends them unkeyed and unlabelled, and its changelog calls them new (A273, X204). The row expects the settings link first under its key with its label, and the support link under its key with its label. Assisted-by: Claude Code:claude-opus-5-5
The port appended the Settings and Community support links unkeyed and without v1's aria-labels, and its changelog called them new (A273, X204). The settings link leads the action links under v1's settings key with the aria-label "View settings", and the support link joins the row's meta under v1's support key with "Visit community forums". The plugin-row-links fragment goes, since v1 had both links. Assisted-by: Claude Code:claude-opus-5-5
The get_group_fields bridge builds each field's id from its group and v1 key and lets that id override the field's own, so a v1 extension that names its option loses it (A343, X216). The row adds a v1 field with its own id and expects that id among the section's fields, not the one built from its key. Assisted-by: Claude Code:claude-opus-5-5
The bridge put the id it builds from the group and v1 key ahead of the field, so the union dropped an id the field set itself and stored the field under another option (A343, X216). A field's own string id wins, and the built id applies only to a field without one; the hook-names line says the fields stay keyed by their v1 ids and keep an id they set. Assisted-by: Claude Code:claude-opus-5-5
The nonce row expected a RuntimeException, which the redirect's UnexpectedValueException also is, so the row passed with the nonce check removed (A475, X238). The die handler throws an anonymous LogicException, and the row expects it and finds the parent without children; with the check removed, the row now errors on the redirect. Assisted-by: Claude Code:claude-opus-5-5
WordPress, WooCommerce and PHPUnit hold about 103 MB before the first row, and the suite's 304 rows peak at about 127 MB, so under the tests container's 128 MB CLI default a random order could end the run with a memory fatal. The PHPUnit configuration sets memory_limit to 256M, WordPress's own admin ceiling, for the suite and the processes it starts. Assisted-by: Claude Code:claude-opus-5-5
Four classes each created, guarded and deleted a throwaway user, two loaded the admin screen API and a third required it inside a helper, four stashed an option by hand, and AutocompletionTest restored an absent option as an empty string; SettingsTest used setUpBeforeClass(), two providers sat below the rows, DeprecatedApiTest read the plugin header twice, and one recorder was not static (A517, A530, A607). CreatesUsersTrait inserts a user, stops on a failed insert so cleanup cannot delete a user the site had, and deletes its users after the row; LoadsAdminScreensTrait loads the screen and meta box API once per class; the stashing classes use RestoresOptionsTrait, whose snapshot now runs before every other hook. SettingsTest builds its tab in a BeforeClass hook, the providers lead their classes, DeprecatedApiTest reads the header once, and the recorder is static. Assisted-by: Claude Code:claude-opus-5-5
The uninstall and partial-deploy rows restored the shared database after their assertions, so a failing row left the consent, the grants or the migrated settings gone for every later row; the consenting rows re-added grants by hand without refreshing roles; two partial-deploy rows built the same failing include; the lock row repeated the self-link assertion; the temp files kept the template's prefix; and LinkingTest's background request named the scoped Lock as a literal on its own command line (A526-A528, A532, A533, A578). Each destructive row restores in finally: the uninstall rows through one fresh request that migrates, runs the runner's hook and grants again, then refreshes this process's caches and roles; the partial-deploy consent row puts back the consent it found. The two include rows are one request, the lock row loses the repeated line, the temp files take the plugin's prefix, and the background request builds its class name from Lock::class and its command through RunsRequestsTrait::command(). Assisted-by: Claude Code:claude-opus-5-5
No row linked an order type another plugin registers, which v1 1.2.0 advertised; the asset row ran on one storage, pinned neither its capability gate nor the editor, and its "not loaded" check passed only because the handle could not register twice; the depth row never let the allowed maximum exceed the stored depth; and the autocompletion rows left a second note and the root's status unpinned (A540, A544, A552, A554). A fixture order class and RegistersOrderTypeTrait register a type through wc_register_order_type() and the supported-types filter, and one ListTable and one MetaBox row on every storage expect the column, the cell, the filter's label, the box's title and names, and links to that type's list. The asset row runs on every storage, dequeues and deregisters before each screen, and expects nothing on a posts list, on the posts editor, or for a user without the column. The depth row raises the maximum to 5, and the autocompletion rows expect one note per descendant and the root at the filtered status. Assisted-by: Claude Code:claude-opus-5-5
The renamed-hook rows proved only that each v1 literal fires before its v2 name, so a relay that passed the v2 listener the original value, or other arguments, still passed (A545, X247). The v1 listener records its arguments and returns a value of its own, negated, suffixed or extended by type, and each row expects the v2 listener to receive that value and the same further arguments. The list helper loads no admin includes of its own, since the class's trait loads them. Assisted-by: Claude Code:claude-opus-5-5
The readme row compared header fields only, while the WooCommerce floor appears in the Installation section and the 2.0.0 Upgrade Notice as prose, so a raised floor could leave either behind (A553, X248). A Unit row expects "WooCommerce" and the entry's WC requires at least in both places; with the Installation sentence set back to 11.2, it fails. Assisted-by: Claude Code:claude-opus-5-5
The child-creation row's URL check also matched the parent's editor, so it could read the parent's id as the child's, and the settings row assumed the site kept the default depth (A564, X250). The row waits for an editor URL whose id is not the parent's, and the settings row stores a depth of 3 through WP-CLI, expects it on the section, and puts back the depth it found; it follows the settings link by its accessible name, "View settings". Assisted-by: Claude Code:claude-opus-5-5
The two stand-ins for Sequential Order Numbers Pro carried production docblocks, file headers and unaligned tags, though PHPStan reads them only for the plugin's API and their native types say the rest (A608, X256). Each keeps a comment saying what it stands in for, and the class keeps one aligned @var for its list of orders. Assisted-by: Claude Code:claude-opus-5-5
The list read every filter through one string helper and mixed static and instance helpers; Settings branched on the general group twice through a single-caller helper, and the list computed its deepest level in another; guards hid in ternaries and the autocompletion filter's result went unnamed; translators comments sat above their statements; the node's formatted name sat among its methods; and an arrow function wrapped a plain call (A307-A313, X212). The list reads its two integers and the billing email through the ruled filter_var and is_string idioms and checks the customer and tree keys for presence, and its helpers are instance methods. Settings builds one group-keyed array, and the list computes its deepest level in place. Guards return early, the filter's result is named, the customer pair reads $customer_key and $customer_value, each translators comment sits inside its call, get_formatted_name() joins the getters, and the children map through dws_lowc_get_order_node by name. Assisted-by: Claude Code:claude-opus-5-5
Summaries narrated their code's branches at twice v1's length, the footprint's return shape named six of its ten keys, and docblocks used semicolons and Markdown backticks, with the settings key pattern written twice (A314-A316, X213). Each long summary names its role, and a second paragraph keeps the one why or the return cases a caller needs; the footprint's shape lists all ten keys in the array's order; the semicolons and backticks go, and the key pattern stays only at dws_lowc_find_setting(). Assisted-by: Claude Code:claude-opus-5-5
The readers repeated the option defaults as literals beside DWS_LOWC_OPTION_DEFAULTS, and the four link meta keys and the add-child action and nonce were literals spread across the components, the node and the includes, while Internal Comments and Locked Payment Methods name theirs (A318, A319, X214). The readers fall back to DWS_LOWC_OPTION_DEFAULTS, keeping the validator's floor of 1, and the validator compares its key strictly so PHPStan reads which default applies. DWS_LOWC_META_DEPTH, _PARENT, _CHILDREN and _CREATED_BY live in linking.php, and DWS_LOWC_CREATE_CHILD_ACTION and _NONCE in post-type.php, and every production site uses them; the list's depth query argument keeps its literal, since it names the filter rather than the meta key. Assisted-by: Claude Code:claude-opus-5-5
Settings::SECTION was public, though nothing outside the class reads it, and the contract would hold it through 2.x (A425, X231). The constant is protected; the id itself stays v1's, which links to the section and the tests name as a literal. Assisted-by: Claude Code:claude-opus-5-5
The changelog omitted v1's namespaced classes and their capability constants, DWS_Order_Node turning final, the capability install notice and its AJAX actions, the three Freemius functions, the six init_status filters and the stricter maximum depth; the Upgrade Notice left out the lone-root link refusal and the Freemius removal; and the README said WordPress shows the notice below every floor (A274-A280, X204). New fragments record the classes and constants, the final node and the depth validation; the 2.0.0 block says capabilities are granted automatically and v1's install notice and its AJAX actions are gone; the freemius and notice-markup-hooks fragments name what they missed; the Upgrade Notice adds both breaks in 292 characters; and the README says WordPress's notice covers the PHP and WordPress floors and the plugin's covers WooCommerce's. Assisted-by: Claude Code:claude-opus-5-5
The docs kept template text that does not fit Linked Orders: a POSIX shell for npm run start, recurring jobs, restrictions in an empty safeguards file, a safeguard rule naming a function the plugin lacks, and a Variants convention for variants it does not have. ARCHITECTURE counted three link keys and listed four, the README said three functions return DWS_Order_Node, and the tests README's gate sentence and Quality line named checks they do not run (A588, A654, A657, A662, A664, X160, X263-X265). The shell clause goes, the scheduler keeps "its scheduled hooks", and the safeguards file is an empty slot whose convention states the rule a future safeguard follows, after the template's recipe and X rulings 164 and 361. The Variants convention goes and the rest renumber. The link keys read "plus _dws_lo_created_by", the README describes linking, child creation and traversal separately, and the tests README names what quality-check runs, the PHP 7.4 parse left to CI, and the readme.txt lint. Assisted-by: Claude Code:claude-opus-5-5
The orders list and the link repair each chose between a meta query and a top-level meta key by the order storage, with its own reason and its own phpcs:ignore, so a change in how either storage takes the key had two places to land. dws_lowc_get_meta_key_args() holds the choice and its reason, and both queries add their own arguments to what it returns. Assisted-by: Claude Code:claude-opus-5-5
The revision row read the stored revision as the site's boot left it, but the update's second step runs its batches only from the runner's scheduled hook, so on a new site the revision stays at 1 until the hook runs. It passed only where an earlier row had fired the hook, and failed in the shared environment's random order. The row fires the hook in a request of its own, as the scheduler would, flushes this process's cache, and then expects the code's revision. Assisted-by: Claude Code:claude-opus-5-5
The orders list's axe pass covered the whole top table navigation, so it also audited WooCommerce's own customer, date and created-via filters, whose missing accessible names Linked Orders does not render and cannot fix (X133). The pass includes only the depth filter, as the meta box's pass includes only the plugin's box. Assisted-by: Claude Code:claude-opus-5-5
The rows pinned "Add new child order", "Root order", "Showing orders linked to #12" and the other strings that name an order mid-sentence, which read wrong on a quote or any other order type Linked Orders links, and say "order" where the child's creator makes another type (X378). The test order type names its own add-child and box phrases through two slug-rooted label keys, while WooCommerce's orders cover the fallback; the depth cell, the filter, the filter lines, the row actions, the box link, the autocompletion note and the refusals expect wording with no type noun, or the type's label first. Assisted-by: Claude Code:claude-opus-5-5
The admin named an order mid-sentence, as "Add new child order" or "Showing orders linked to #12", which reads wrong on a quote or any other order type Linked Orders links, and the add-child phrases could not say a quote at all, since a child takes the type its creator makes, which only the type's registrant knows (X378). Strings drop the type noun where the screen already shows the type, refusals open with the type's label and number, and the add-child button, the row action and the box title read whole phrases an order type registers under two slug-rooted label keys, falling back to "Add new child order" and "Linked orders". The keys join the contract, the README and a changelog fragment. Assisted-by: Claude Code:claude-opus-5-5
The row fired the runner's hook and read the revision, but on a site already at the code's revision, as after the migration rows restore it, both assertions held without any step running. The row stores the revision before the batched step first, so it passes only once the hook runs that step. Assisted-by: Claude Code:claude-opus-5-5
A quote's box titled "Linked quotes" would list the order the quote became, since the box shows the parent and children whatever their types, so the box-title label misnamed its own contents (X380). The autocompletion note "Completed with its linked parent." was false where the filter skipped the parent or set another status, and the add-child phrase and its fallback sat in two classes. Every box reads "Linked orders", escaped like any title WordPress prints; one helper words the add-child phrase from the remaining label key; the note reads "Status set when a linked ancestor was completed."; the README tells a registrant to set the label together with the creator it swaps in. Assisted-by: Claude Code:claude-opus-5-5
The walk starts at the completed order itself, so where the status filter names another status, that order got "Status set when a linked ancestor was completed." although it may have no ancestor. The note reads "Status set by Linked Orders' autocompletion.", and the status-filter row checks the completed order's note too. Assisted-by: Claude Code:claude-opus-5-5
The rows held the v1 hook-tag builders to v1's sanitizing of spaces, backslashes, case and high bytes and to its null for an unknown component, and held Sequential Order Numbers Pro to numbering a child inside the deprecated v1 action, all for callers and listeners no plugin has (X381). The builder rows expect their parts joined with slashes, a name for any component id included; the numbering row expects a listener of the deprecated action to see the child unnumbered and a later listener of the v2 action to see the number and replace it. Assisted-by: Claude Code:claude-opus-5-5
v1's hook-tag builders went through a shared helper that copied v1's sanitizing and a list of v1's component ids, Sequential Order Numbers Pro joined the deprecated v1 action through deprecated_hook_run to number a child where v1 did, and two constants each served one line, one of them added to the contract, all for callers and listeners no plugin has (X381). Each builder joins its parts with slashes in one line; the integration numbers a child on the v2 action alone, which a changelog fragment records; the add-child label key and v1's settings groups are written where they are read. Assisted-by: Claude Code:claude-opus-5-5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Linked Orders' v1 installations upgrade in place with links v1 left inconsistent, and the port audit left items in the plugin. This repairs and protects the order links: a batched update step roots the children of orders v1 deleted, lists each child its parent lost and stores each child one level below its parent; deleting an order for good, through WooCommerce or WordPress's posts API, makes its children roots; tree walks stop at an order they visited; a link saves the child first and its parent only once the child reads back; and a creator's order that is the parent or already linked is refused before it is touched. Child creation checks the order's own edit capability, rows read their own links and autocompletion completes each order once. The admin copy says why a child cannot be created and which filter the list shows, new-tab links announce it and the depth filter is named. v1 behaviors the port changed without a ruling come back, the changelog and readme record v1's breaks, the docs fit the plugin, and the root and every plugin move to WooCommerce 11.3.
Type of change
Checklist
composer changelog:addin the changed plugin's directory)composer quality-checkpasses locally in every changed plugin: each check it runs passed, Integration through PHPUnit in each site, since the script's asset build callswp-scripts, which a local hook blocksreadme.txtupdated if runtime requirements changedBreaking changes
WC requires at least, the constraints and the readmes).manage_woocommerce, beside v1's create capability.dws_lowc_link_orders()saves the child first and the parent only once the child reads back;dws_lowc_create_linked_child()refuses a creator's order that is the parent or already linked.dws_lowc/settings/validated_valuefor an id no group maps too, with the group's-settingssuffix removed.