Skip to content

Latest commit

 

History

History
343 lines (319 loc) · 27.6 KB

UPGRADE-14.0.md

File metadata and controls

343 lines (319 loc) · 27.6 KB

UPGRADING FROM 13.x to 14.0

The releases of Shopsys Platform adhere to the Backward Compatibility Promise to make the upgrades to new versions easier and help long-term maintainability.

Recommended way of upgrading

Since there are 3 possible scenarios for using Shopsys Platform, instructions are divided into these scenarios.

You use our packages only

Follow the instructions in relevant sections, e.g. shopsys/coding-standards or shopsys/http-smoke-testing.

You are developing a project based on the project-base repository

  • upgrade only your composer dependencies and follow the instructions in the guide below
  • upgrade locally first - after you fix all issues caused by the upgrade, commit your changes, test your application, and then continue with a deployment onto your server
  • upgrade one version at a time:
    • start with a working application
    • upgrade to the next version
    • fix all the issues you encounter
    • repeat
  • check the instructions in all sections; any of them could be relevant to you
  • the typical upgrade sequence should be:
    • run docker-compose down --volumes to turn off your containers
    • (macOS only) run mutagen-compose down --volumes instead
    • follow upgrade notes in the Infrastructure section (related to docker-compose.yml, Dockerfile, docker containers, nginx.conf, php.ini, etc.)
    • (MacOS, Windows only) run docker-sync start to create volumes
    • run docker-compose build --no-cache --pull to build your images without cache and with the latest version
    • run docker-compose up -d --force-recreate --remove-orphans to start the application again
    • update the shopsys/* dependencies in composer.json to the version you are upgrading to
      • e.g., "shopsys/framework": "v7.0.0"
    • follow upgrade notes in the Composer dependencies section (related with composer.json)
    • run composer update shopsys/* --with-dependencies
    • update the @shopsys/framework package in your package.json (in "dependencies" section) to the version you are upgrading to
      • eg. "@shopsys/framework": "9.0.4",
    • run npm install to update the NPM dependencies
    • follow all upgrade notes you have not done yet
    • run php phing clean
    • run php phing db-migrations to run the database migrations
    • test your app locally
    • commit your changes
    • run composer update to update the rest of your dependencies, test the app again, and commit composer.lock
  • if any of the database migrations do not suit you, there is an option to skip it; see our Database Migrations docs
  • we may miss something even if we care a lot about these instructions. In case something doesn't work after the upgrade, you'll find more information in the CHANGELOG
  • add rounded price value to order process (#2835)
    • see #project-base-diff to update your project
  • remove link from administrator and customers breadcrumb (#2881)
    • see #project-base-diff to update your project
  • add test to keep Elasticsearch converter and mapping in sync (#2880)
    • see #project-base-diff to update your project
  • set products for export to elastic after changing quantity after completing, editing, or deleting order (#2587)
    • method Shopsys\FrameworkBundle\Model\Order\Item\OrderProductFacade::__construct() changed its interface:
          public function __construct(
              protected readonly EntityManagerInterface $em,
              protected readonly ProductHiddenRecalculator $productHiddenRecalculator,
              protected readonly ProductSellingDeniedRecalculator $productSellingDeniedRecalculator,
              protected readonly ProductAvailabilityRecalculationScheduler $productAvailabilityRecalculationScheduler,
              protected readonly ProductVisibilityFacade $productVisibilityFacade,
              protected readonly ModuleFacade $moduleFacade,
      +       protected readonly ProductRepository $productRepository,
          )
  • update your project to fix problems with single domain (#2875)
    • see #project-base-diff to update your project
  • improve product lists in GrapesJS (#2879)
    • see #project-base-diff to update your project
  • add Symfony Messenger along with RabbitMQ (#2898)
    • install application to create new necessary containers (run again ./scripts/install.sh) – this will overwrite your local docker-compose.yml file
    • see #project-base-diff to update your project
  • set the custom logger to the Frontend API (#2882)
    • you can set shopsys.frontend_api.validation_logged_as_error parameter to true to log validation errors with log level ERROR instead of INFO
    • see #project-base-diff to update your project
  • start formatting markdown files with Prettier (#2892)
    • see #project-base-diff to update your project
    • reformat your markdown files by running php phing standards-fix in php-fpm container
    • standards(-fix) targets runs newly added markdown-check/markdown-fix target, so if you have completely changed the standards(-fix) target, remember to add those into your standards(-fix) target
  • speed up Product creation in your project (#2903)
    • method Shopsys\FrameworkBundle\Component\Router\FriendlyUrl\FriendlyUrlFacade::resolveUniquenessOfFriendlyUrlAndFlush() has been renamed to resolveUniquenessOfFriendlyUrl as it no longer flushes
    • method Shopsys\FrameworkBundle\Model\Product\Pricing\ProductManualInputPriceFacade::refresh() has changed its visibility to protected
    • method Shopsys\FrameworkBundle\Model\Product\ProductFacade::refreshProductManualInputPrices() has been moved to Shopsys\FrameworkBundle\Model\Product\Pricing\ProductManualInputPriceFacade::refreshProductManualInputPrices() and changed its visibility to public
    • method Shopsys\FrameworkBundle\Model\Product\Pricing\ProductManualInputPriceFacade::__construct() changed its interface:
        public function __construct(
            protected readonly EntityManagerInterface $em,
            protected readonly ProductManualInputPriceRepository $productManualInputPriceRepository,
            protected readonly ProductManualInputPriceFactoryInterface $productManualInputPriceFactory,
    +       protected readonly PricingGroupRepository $pricingGroupRepository,
        )
    • method Shopsys\ProductFeed\GoogleBundle\Model\Product\GoogleProductDomainFacade::saveGoogleProductDomain() changed its visibility to protected
    • method Shopsys\ProductFeed\HeurekaBundle\Model\Product\HeurekaProductDomainFacade::saveHeurekaProductDomain() changed its visibility to protected
    • method Shopsys\ProductFeed\HeurekaBundle\Model\Product\HeurekaProductDomainFacade::saveHeurekaProductDomain() changed its visibility to protected
    • method Shopsys\ProductFeed\ZboziBundle\Model\Product\ZboziProductDomainFacade::saveZboziProductDomain() changed its visibility to protected
    • see #project-base-diff to update your project
  • add consumers and RabbitMQ to deployed application (#2904)
    • set new environment variables RABBITMQ_DEFAULT_USER, RABBITMQ_DEFAULT_PASS, RABBITMQ_IP_WHITELIST in your deployment tool (with use of the default config it will be Gitlab CI)
    • see #project-base-diff to update your project
  • re-enable phing target cron (#2875)
    • see #project-base-diff to update your project
  • prepare core for dispatch/consume system (#2907)
    • your custom classes that utilize internal array caching or need to be reset between message consumption should now implement the \Symfony\Contracts\Service\ResetInterface interface
    • method Shopsys\FrameworkBundle\Model\Product\Pricing\ProductPriceRecalculationScheduler::cleanScheduleForImmediateRecalculation() has been renamed to reset()
    • see #project-base-diff to update your project
  • replace custom application bootstrapping with symfony/runtime (#2914)
    • see #project-base-diff to update your project
  • prevent duplicate color parameters in data fixtures (#2911)
    • see #project-base-diff to update your project
  • enable crons to be run at specified times the same as crons ()
    • replace HourlyFeedCronModule and DailyFeedCronModule with FeedCronModule in config/services/cron.yaml and set it to be run every time crons are run to ensure that all feeds are generated
    • FeedExportCreationDataQueue has changed, first parameter is now an array of Shopsys\FrameworkBundle\Model\Feed\FeedModule instances instead of module names
    • method Shopsys\FrameworkBundle\Model\Feed\FeedFacade::__construct() changed its interface:
        public function __construct(
            protected readonly FeedRegistry $feedRegistry,
            protected readonly ProductVisibilityFacade $productVisibilityFacade,
            protected readonly FeedExportFactory $feedExportFactory,
            protected readonly FeedPathProvider $feedPathProvider,
            protected readonly FilesystemOperator $filesystem,
    +       protected readonly FeedModuleRepository $feedModuleRepository,
    +       protected readonly EntityManagerInterface $em,
        )
    • method Shopsys\FrameworkBundle\Model\Feed\FeedFacade::getFeedsInfo() changed its interface:
    -    public function getFeedsInfo(?string $feedType = null): array
    +    public function getFeedsInfo(bool $onlyForCurrentTime = false): array
    • method Shopsys\FrameworkBundle\Model\Feed\FeedFacade::getFeedsNames() changed its interface:
    -    public function getFeedNames(?string $feedType = null): array
    +    public function getFeedNames(bool $onlyForCurrentTime = false): array
    • method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::__construct() changed its interface:
        public function __construct(
    -       protected readonly array $knownTypes,
    -       protected readonly string $defaultType,
    +       protected readonly FeedRegistry $feedRegistry,
    +       protected readonly ProductVisibilityFacade $productVisibilityFacade,
    +       protected readonly FeedExportFactory $feedExportFactory,
    +       protected readonly FeedPathProvider $feedPathProvider,
    +       protected readonly FilesystemOperator $filesystem,
    +       protected readonly FeedModuleRepository $feedModuleRepository,
    +       protected readonly EntityManagerInterface $em,
        )
    • method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::registerFeed() changed its interface:
    -    public function registerFeed(FeedInterface $feed, ?string $type = null): void
    +    public function registerFeed(FeedInterface $feed, string $timeHours, string $timeMinutes, array $domainIds): void
    • property Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::$feedsByType has been replaced with new $feedConfigsByName property instead
    • method Shopsys\FrameworkBundle\Controller\Admin\FeedController::__construct changed its interface:
        public function __construct(
            protected readonly FeedFacade $feedFacade,
            protected readonly GridFactory $gridFactory,
            protected readonly Domain $domain,
    +       protected readonly FeedRegistry $feedRegistry,
    +       protected readonly FeedModuleRepository $feedModuleRepository,
        )
    • method Shopsys\FrameworkBundle\Model\Feed\Exception\FeedNotFoundException__construct changed its interface:
        public function __construct(
            string $name, 
    +       ?int $domainId = null, 
            ?Exception $previous = null
        )
    • method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getFeeds() has been replaced with method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getFeedsForCurrentTime()
    • method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getAllFeeds() has been replaced with method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getAllFeedConfigs()
    • method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getFeedByName() has been replaced with method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getFeedConfigByName()
    • method Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::assertTypeIsKnown() has been removed without a replacement
    • see #project-base-diff to update your project

Storefront

  • add rounded price value to order process (#2835)

    • see #project-base-diff to update your project
  • remove unnecessary default value for domain config in zustand (#2888)

    • you probably do not need the default value as well, as we set it right at the beginning of page load
    • see #project-base-diff to update your project
  • fixed undefined window error (#2882)

    • in one of the previous PR's, the canUseDom function was removed, but it caused the application to fail in some cases
    • because of that, the function was brought back as a constant (as isClient) and some checks were reinstantiated
    • in your code, you should pay attention to where you are using the window object and make sure it is available (either by checking the logic or by explicitly wrapping it in a check)
    • also keep in mind that canUseDom is now isClient and isServer is now used as !isClient
    • for not-discussed changes, see #project-base-diff to update your project
  • add Prettier plugin and ESlint plugins and rules (#2874)

    • see #project-base-diff to update your project
    • to check if your repo follows the new rules run pnpm run check or pnpm run check--fix to autofix in Storefront folder or in Storefront Docker container
    • Prettier
      • added @trivago/prettier-plugin-sort-imports plugin
    • ESlint
      • added eslint-plugin-no-relative-import-paths plugin and rules enforcing rules for imports
      • new rules
        • no-helpers-are-exported-from-component-file
        • react/jsx-no-useless-fragment
        • react/self-closing-comp
        • react/jsx-sort-props
        • no-relative-import-paths/no-relative-import-paths
  • add Related Products tab on product detail page (#2885)

    • see #project-base-diff to update your project
  • improve product lists in GrapesJS (#2879)

    • see #project-base-diff to update your project
  • add instant page skeleton after link click (#2863)

    • before page must first load and then skeleton was shown, now we pass page type to ExtendedLink component which allow us to display immediately after user click on the link proper skeleton for the required page
    • some reorganization and renaming was done to Skeletons, we basically have only two types of skeletons, for pages and modules, since it is sometimes difficult to recognise which one is which, we have added Page word, but this was not perfect in folder organization, that's why it's been added word Module as well, to organize skeletons better way
    • added missing skeletons for Homepage and Stores
    • adjustments to current skeletons to match the design of a page better
    • see #project-base-diff to update your project
  • refactoring of various error-related matters on SF (#2871)

    • the goal was to shine light on some of the not-well-understood places in regard of error handling on SF
    • for you to get the most out of this PR, you should check error-handling.md in SF docs, which is a direct result of this PR
    • it contains explanations and tips on how to improve error handling in your SF code as well
    • for not-discussed changes, see #project-base-diff to update your project
    • see #project-base-diff to update your project
  • refactor ProductVariantsTable (#2899)

    • ProductVariantsTable component was made with table element but on smaller screens it was styled more like list. This was causing styling difficulties. That's why it has been replaced with grid with combination of flexbox.
    • components ProductVariantsTableRow and Variant were removed
    • component ProductVariantsTable was renamed to ProductDetailVariantsTable so it matches parent folder where it's placed
    • see #project-base-diff to update your project
  • add equal spacing to the Category page (#2900)

    • see #project-base-diff to update your project
  • auth (loading) improvements (#2897)

    • window.location.href assignments were replaced with router operations because of unexpected behavior, where the current URL (thus also properties of the router) changed even before the transition, which caused useEffects and some other conditions to re-run and potentially fails

    • if you manipulate window.location in your code, you should remove it and use router instead

    • loading states for all auth operations (login, logout, registration) are now implemented, so if you have some custom states, you should also handle these

    • optimistic display of skeletons was implemented for logout-loading and both registration-loading...states

      • this was possible as we know that the user is going to be redirected to homepage
      • however, since we do not know the page type of the redirect destination after login, we do not display any skeleton there
      • if you always know the destination of redirect after login, chances are you can improve the UX by implementing the following changes:
      // inside useAuth.tsx login
      updateAuthLoadingState(
          loginResult.data.Login.showCartMergeInfo ? 'login-loading-with-cart-modifications' : 'login-loading',
      );
      
      // add this line to start showing the skeleton before the redirect
      updatePageLoadingState({
          isPageLoading: true,
          redirectPageType: 'my-page-type',
      });
      
      if (rewriteUrl) {
          router.replace(rewriteUrl).then(() => router.reload());
      } else {
          router.reload();
      }
  • added USPs on product detail page (#2887)

    • see #project-base-diff to update your project
  • fix sizes of product actions buttons (#2896)

    • now we have unified sizes of add to cart buttons
    • see #project-base-diff to update your project
  • fix Comparison for not logged in users (#2905)

    • unified code for Comparison and Wishlist
    • refactored Zustand store to use only one store (User Store) for all cartUuid, wishlistUuid and comparisonUuid
  • search on search page is now not called if search query is empty (#2895)

    • see #project-base-diff to update your project
  • fix set default delivery address country (#2902)

    • see #project-base-diff to update your project
  • fix router server access error on PageGuard (#2909)

    • see #project-base-diff to update your project
  • fix Cart list unit text (#2910)

  • remove Heading component (#2894)

    • it was decided by FE team that this component is not beneficial
    • it was replaced with general H tags and styles were put into globals.css, styles were also included with new classes (h1, h2, h3, h4) which we can use to style text which suppose to look like heading but it is not important enough for mark with H tag
    • also from those headings and heading classes was remove margin bottom since spacing should be set in exact place where this component is used, not everywhere
    • see #project-base-diff to update your project
  • remove error logging for when gtmSafePush is called outside of the client (#2920)

    • logging this type of error brought no business value, thus it was removed
    • if you want to treat this ignorable event in a more strict way, you might want to keep the logging, but then you have to improve its behavior yourself
    • see #project-base-diff to update your project
  • added logic for ordering GTM events (#2921)

    • added a GTM context provider for synchronizing events
    • if you have any logic for syncing your events, you can move it to this provider
    • docs were added, so you can base your changes on those
    • see #project-base-diff to update your project
  • improve SEO categories logic in regards to non-SEO-sensitive filters (#2891)

    • we moved some config from various files to config/constants and warmly suggest you do the same, as it improves the app and testing
    • we also moved some hooks from helpers to hooks and suggest you do the same with all hooks, as it again improves the app and testing
    • the implemented functionality for dynamic switching between SEO-sensitivity for various filters is only implemented on SF, so applying these changes won't make it work on BE
    • if you do not need SEO categories, these changes might be irrelevant altogether
    • flag and brand values are now merged after change of default parameters (leaving SEO category) instead of overwritting. This is a bug fix and you should apply it to your changes as well.
    • see #project-base-diff to update your project
  • category data fetching logic improvements (#2893)

    • these changes primarily focus on fixing loading and fetching logic on the category page
    • there were certain bugs with double loads, skeleton glitches, etc. but they were mostly caused by the added complexity of SEO categories, so if you do not have those and your fetching logic is thus much simpler, you probably do not need most of these changes
    • the category detail fetching was also rewritten to the generated URQL hook, which can be beneficial for you if your logic allows you to do so
    • one thing that you should definitely consider is removal of onRouteChangeError from the page loading logic, as the previous implementation was rather invalid. See commit message for more details
  • added additional skeletons, sync store across browser tabs, use BroadcastChannel to refresh cart after Add/Remove to/from cart, ExtendedNextLink was refactored, remove EmptyCartWrapper (#2906)

    • added skeletons for Wishlist, Comparison and My orders, Order detail and Product Main Variant page

    • fix Add to cart/wishlist/comparison feature when using multiple tabs

      • Before this change if I open multiple tabs as fresh unlogged user without cartUuid, then in each tab I add product to cart, I am experiencing that each tab contains different products in cart, even after refresh. Same applies to Wishlist and Comparison. This is solved now by adding BroadcastChannel middleware to Zustand store, so now it uses always only first returned uuid.
      • removed redirect to homepage after logout, this was not good approach
      • removeItemFromCartAction in useRemoveProductFromCart is now void type (doesn't return CartFragmentApi) and in case of error is returned from API it refect cart so user gets latest cart updates
      • Zustand package is upgraded to latest version
      • We are now manually hydrating the Zustand store during the initial page load. This means that we no longer need to resolve mismatches between the UI rendered by the server and the UI managed on the client side. Code from this example may look familiar to you, this is no longer needed:
      const [isFetchingPaused, setIsFetchingPaused] = useState(true);
      
      const [{ data: comparisonData, fetching }] = useComparisonQueryApi({
          variables: { comparisonUuid },
          pause: isFetchingPaused,
          pause: !comparisonUuid && !isUserLoggedIn,
      });
      
      useEffect(() => {
          setIsFetchingPaused(!comparisonUuid && !isUserLoggedIn);
      }, [comparisonUuid]);
    • fix Add to cart/wishlist/comparison feature when using multiple tabs

      • As fresh unlogged user without cartUuid I open multiple tabs, then in each tab I add product to cart, I am experiencing that each tab contains different products in cart, even after refresh. Same applies to Wishlist and Comparison. This was solved by adding BroadcastChannel middleware to Zustand store, so now it uses always only first returned uuid.
      • Added useBroadcastChannel hook, this allow us to use Broadcast Channel for better handling multitab behavior. Together with the first type Auth for handling Authentication. Now when user log in/out, other tabs are reloaded.
    • ExtendedNextLink was refactored

      • remove static type from your links
      • if you have custom types, we moved it from STATIC_PAGES to CUSTOM_PAGES
    • use BroadcastChannel to refresh cart

      • whereever you use modifications for cart there should be also implemented the same behavior
      • Removed isCartEmpty value from useCurrentCart. This was causing unnecessary checks for cart value after check if isCartEmpty, because Typescript was not able to recognise that cart value is already checked. For the same reason some handling cases were more difficult to write and understand. Also check for cart exist (!cartUuid && !isUserLoggedIn) was needed basically everywhere where cart values were using, this was added to this hook and now cart value is consistent
    • remove EmptyCartWrapper

      • this component was making whole order process very difficult to predict behavior, now we have the logic from this component splitted into each page of the order process which makes it much more predictable
      • also this fixes bug with infinite cart page loading