Type key to the words a merchant reads. */ function addon_boss_field_type_menu( string $keep = '' ): array { $out = array(); foreach ( addon_boss_personalisation_field_types() as $type => $def ) { $type = (string) $type; if ( ! addon_boss_field_type_available( $type ) && $type !== $keep ) { continue; } // A type's menu wording is what it is offered as; the label is its // shorter name for lists and columns. Menu first, so the merchant reads // the same words wherever the type is met. $out[ $type ] = (string) ( $def['menu'] ?? $def['label'] ?? $type ); } return $out; } /** * Is this fee mode offered by this build? * * Per-letter, percentage and per-value pricing ride with the fee-modes module; * a flat fee, charged once or for each, is the engine's own. A field priced by * an unavailable mode keeps its input and charges nothing, and the merchant's * stored fee is left untouched. */ function addon_boss_fee_mode_available( string $mode ): bool { return in_array( $mode, array( 'char', 'percent', 'per_value' ), true ) ? addon_boss_engine_can( 'fee-modes' ) : true; } /** * Which product types can carry option sets on their own page. * * A simple product is the engine's own surface. A variable parent rides with the * module that reconciles two choice systems on one page (its variations and its * sets), so without that module a variable parent offers none. * * @return string[] */ function addon_boss_options_product_types(): array { $types = array( 'simple' ); if ( addon_boss_engine_can( 'variable-options' ) ) { $types[] = 'variable'; } return $types; } // Engine modules - the addon_boss_* primitives, lifted from BundleBoss at the // split. Required via __DIR__ so the engine always loads its own siblings. require_once __DIR__ . '/swatches.php'; require_once __DIR__ . '/pricing.php'; require_once __DIR__ . '/variations.php'; // The standalone options engine: option sets, product fields, the fee and value // maths, the resolvers, virtual variations and the grid split. This is the // engine's own surface and a normal file, present in every build. require_once __DIR__ . '/standalone.php'; // The option set preview panel on the set editor: the draft form rendered // as shoppers will see it, through the same sanitiser and renderer the real // save and the real page use. Nothing is persisted by previewing. require_once __DIR__ . '/set-preview.php'; // Conditional reveal: the show/hide rules on sets and fields. The basic // vocabulary (is, is not, is any of, answered, empty) runs in every build; // the numeric compares ask the 'reveal' capability and stand down to // "simply shows" without it. require_once __DIR__ . '/reveal.php'; // Reading a variable product into option sets, and building the option version // beside it as a draft. Present in every build: the merchant who needs it most // is the one who has not paid yet. What it cannot carry (a SKU per pair, and // stock per pair without the plan) it says out loud before it writes anything. // What a pair weighs and measures, and the pair key both maps are stored // under. Free: wrong postage costs a merchant money on every order. require_once __DIR__ . '/combo-shipping.php'; require_once __DIR__ . '/variation-convert.php'; // Optional engine modules. // // Anything in pro/ is loaded, in name order. Each one defines its own functions // and registers its own hooks, so a directory with nothing in it simply means // the engine has no code for those things, the same as any other feature it was // never written to do. There is nothing to switch on or off here and nothing to // ask: a module either exists on disk or it does not. // // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- transient file-scope path holders, unset immediately below. $bb_engine_modules = glob( __DIR__ . '/pro/*.php' ); if ( is_array( $bb_engine_modules ) ) { sort( $bb_engine_modules ); foreach ( $bb_engine_modules as $bb_engine_module ) { require_once $bb_engine_module; } } unset( $bb_engine_modules, $bb_engine_module ); // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound // --- more engine modules land here as Phase A proceeds ---