spree_core 5.2.6 → 5.3.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/addresses_helper.rb +1 -23
  3. data/app/helpers/spree/base_helper.rb +25 -77
  4. data/app/helpers/spree/currency_helper.rb +2 -2
  5. data/app/helpers/spree/images_helper.rb +5 -0
  6. data/app/helpers/spree/mail_helper.rb +1 -1
  7. data/app/helpers/spree/products_helper.rb +1 -1
  8. data/app/jobs/spree/events/subscriber_job.rb +58 -0
  9. data/app/jobs/spree/products/refresh_metrics_job.rb +14 -0
  10. data/app/jobs/spree/products/touch_taxons_job.rb +0 -1
  11. data/app/jobs/spree/variants/touch_job.rb +9 -0
  12. data/app/models/concerns/spree/adjustment_source.rb +8 -0
  13. data/app/models/concerns/spree/parameterizable_name.rb +1 -1
  14. data/app/models/concerns/spree/product_scopes.rb +54 -8
  15. data/app/models/concerns/spree/publishable.rb +253 -0
  16. data/app/models/concerns/spree/unique_name.rb +1 -1
  17. data/app/models/concerns/spree/user_methods.rb +21 -1
  18. data/app/models/spree/ability.rb +3 -3
  19. data/app/models/spree/address.rb +0 -3
  20. data/app/models/spree/adjustable/promotion_accumulator.rb +1 -1
  21. data/app/models/spree/adjustment.rb +32 -6
  22. data/app/models/spree/asset.rb +6 -3
  23. data/app/models/spree/base.rb +3 -1
  24. data/app/models/spree/classification.rb +2 -2
  25. data/app/models/spree/credit_card.rb +0 -3
  26. data/app/models/spree/current.rb +24 -3
  27. data/app/models/spree/custom_domain.rb +1 -1
  28. data/app/models/spree/customer_group.rb +94 -0
  29. data/app/models/spree/customer_group_user.rb +16 -0
  30. data/app/models/spree/customer_return.rb +2 -3
  31. data/app/models/spree/digital.rb +2 -4
  32. data/app/models/spree/digital_link.rb +2 -3
  33. data/app/models/spree/event.rb +104 -0
  34. data/app/models/spree/export.rb +7 -1
  35. data/app/models/spree/gift_card.rb +13 -1
  36. data/app/models/spree/gift_card_batch.rb +3 -1
  37. data/app/models/spree/image.rb +20 -5
  38. data/app/models/spree/import.rb +17 -12
  39. data/app/models/spree/import_row.rb +13 -26
  40. data/app/models/spree/inventory_unit.rb +0 -3
  41. data/app/models/spree/invitation.rb +12 -6
  42. data/app/models/spree/line_item.rb +57 -4
  43. data/app/models/spree/newsletter_subscriber.rb +2 -0
  44. data/app/models/spree/option_type.rb +2 -5
  45. data/app/models/spree/option_value.rb +1 -4
  46. data/app/models/spree/order/checkout.rb +7 -2
  47. data/app/models/spree/order/emails.rb +3 -11
  48. data/app/models/spree/order/store_credit.rb +5 -1
  49. data/app/models/spree/order.rb +80 -31
  50. data/app/models/spree/order_updater.rb +28 -9
  51. data/app/models/spree/payment/custom_events.rb +37 -0
  52. data/app/models/spree/payment.rb +13 -4
  53. data/app/models/spree/payment_capture_event.rb +0 -4
  54. data/app/models/spree/payment_method.rb +1 -1
  55. data/app/models/spree/permission_sets/default_customer.rb +3 -3
  56. data/app/models/spree/policy.rb +1 -8
  57. data/app/models/spree/post.rb +2 -7
  58. data/app/models/spree/post_category.rb +2 -0
  59. data/app/models/spree/price.rb +8 -6
  60. data/app/models/spree/price_list.rb +263 -0
  61. data/app/models/spree/price_rule.rb +26 -0
  62. data/app/models/spree/price_rules/customer_group_rule.rb +21 -0
  63. data/app/models/spree/price_rules/user_rule.rb +19 -0
  64. data/app/models/spree/price_rules/volume_rule.rb +21 -0
  65. data/app/models/spree/price_rules/zone_rule.rb +19 -0
  66. data/app/models/spree/product.rb +117 -76
  67. data/app/models/spree/product_property.rb +2 -2
  68. data/app/models/spree/promotion/rules/customer_group.rb +22 -0
  69. data/app/models/spree/promotion/rules/user.rb +2 -2
  70. data/app/models/spree/promotion.rb +3 -4
  71. data/app/models/spree/promotion_handler/coupon.rb +3 -3
  72. data/app/models/spree/property.rb +3 -6
  73. data/app/models/spree/prototype.rb +0 -3
  74. data/app/models/spree/refund.rb +2 -3
  75. data/app/models/spree/reimbursement.rb +5 -3
  76. data/app/models/spree/report.rb +7 -1
  77. data/app/models/spree/reports/products_performance.rb +1 -1
  78. data/app/models/spree/reports/sales_total.rb +1 -1
  79. data/app/models/spree/return_authorization.rb +7 -3
  80. data/app/models/spree/return_item.rb +15 -4
  81. data/app/models/spree/shipment/custom_events.rb +47 -0
  82. data/app/models/spree/shipment.rb +12 -5
  83. data/app/models/spree/shipping_category.rb +0 -3
  84. data/app/models/spree/shipping_method.rb +0 -3
  85. data/app/models/spree/stock/quantifier.rb +1 -1
  86. data/app/models/spree/stock_item.rb +2 -0
  87. data/app/models/spree/stock_location.rb +0 -3
  88. data/app/models/spree/stock_movement/custom_events.rb +44 -0
  89. data/app/models/spree/stock_movement.rb +3 -0
  90. data/app/models/spree/stock_transfer.rb +2 -3
  91. data/app/models/spree/store.rb +64 -92
  92. data/app/models/spree/store_credit.rb +3 -4
  93. data/app/models/spree/store_product.rb +14 -0
  94. data/app/models/spree/subscriber.rb +186 -0
  95. data/app/models/spree/tax_category.rb +0 -4
  96. data/app/models/spree/tax_rate.rb +0 -3
  97. data/app/models/spree/taxon.rb +3 -36
  98. data/app/models/spree/taxonomy.rb +0 -3
  99. data/app/models/spree/variant.rb +114 -21
  100. data/app/models/spree/webhook_delivery.rb +60 -0
  101. data/app/models/spree/webhook_endpoint.rb +53 -0
  102. data/app/models/spree/wished_item.rb +2 -4
  103. data/app/models/spree/wishlist.rb +2 -3
  104. data/app/models/spree/zone.rb +0 -9
  105. data/app/paginators/spree/shared/paginate.rb +4 -0
  106. data/app/serializers/spree/events/asset_serializer.rb +22 -0
  107. data/app/serializers/spree/events/base_serializer.rb +61 -0
  108. data/app/serializers/spree/events/customer_return_serializer.rb +20 -0
  109. data/app/serializers/spree/events/digital_link_serializer.rb +20 -0
  110. data/app/serializers/spree/events/digital_serializer.rb +18 -0
  111. data/app/serializers/spree/events/export_serializer.rb +22 -0
  112. data/app/serializers/spree/events/gift_card_batch_serializer.rb +24 -0
  113. data/app/serializers/spree/events/gift_card_serializer.rb +29 -0
  114. data/app/serializers/spree/events/image_serializer.rb +9 -0
  115. data/app/serializers/spree/events/import_row_serializer.rb +23 -0
  116. data/app/serializers/spree/events/import_serializer.rb +24 -0
  117. data/app/serializers/spree/events/invitation_serializer.rb +28 -0
  118. data/app/serializers/spree/events/line_item_serializer.rb +31 -0
  119. data/app/serializers/spree/events/newsletter_subscriber_serializer.rb +21 -0
  120. data/app/serializers/spree/events/order_serializer.rb +39 -0
  121. data/app/serializers/spree/events/payment_serializer.rb +24 -0
  122. data/app/serializers/spree/events/post_category_serializer.rb +20 -0
  123. data/app/serializers/spree/events/post_serializer.rb +26 -0
  124. data/app/serializers/spree/events/price_serializer.rb +22 -0
  125. data/app/serializers/spree/events/product_serializer.rb +24 -0
  126. data/app/serializers/spree/events/promotion_serializer.rb +32 -0
  127. data/app/serializers/spree/events/refund_serializer.rb +23 -0
  128. data/app/serializers/spree/events/reimbursement_serializer.rb +22 -0
  129. data/app/serializers/spree/events/report_serializer.rb +23 -0
  130. data/app/serializers/spree/events/return_authorization_serializer.rb +22 -0
  131. data/app/serializers/spree/events/return_item_serializer.rb +27 -0
  132. data/app/serializers/spree/events/shipment_serializer.rb +24 -0
  133. data/app/serializers/spree/events/stock_item_serializer.rb +22 -0
  134. data/app/serializers/spree/events/stock_movement_serializer.rb +22 -0
  135. data/app/serializers/spree/events/stock_transfer_serializer.rb +22 -0
  136. data/app/serializers/spree/events/store_credit_serializer.rb +30 -0
  137. data/app/serializers/spree/events/user_serializer.rb +18 -0
  138. data/app/serializers/spree/events/variant_serializer.rb +34 -0
  139. data/app/serializers/spree/events/wished_item_serializer.rb +20 -0
  140. data/app/serializers/spree/events/wishlist_serializer.rb +22 -0
  141. data/app/services/spree/addresses/update.rb +1 -1
  142. data/app/services/spree/cart/add_item.rb +1 -1
  143. data/app/services/spree/coupon_codes/coupon_codes_handler.rb +2 -1
  144. data/app/services/spree/data_feeds/google/required_attributes.rb +4 -4
  145. data/app/services/spree/newsletter/verify.rb +5 -0
  146. data/app/services/spree/products/auto_match_taxons.rb +1 -1
  147. data/app/services/spree/seeds/all.rb +1 -1
  148. data/app/services/spree/taxons/add_products.rb +8 -4
  149. data/app/services/spree/taxons/regenerate_products.rb +8 -0
  150. data/app/services/spree/taxons/remove_products.rb +12 -7
  151. data/app/subscribers/spree/event_log_subscriber.rb +64 -0
  152. data/app/subscribers/spree/export_subscriber.rb +26 -0
  153. data/app/subscribers/spree/invitation_email_subscriber.rb +40 -0
  154. data/app/subscribers/spree/product_metrics_subscriber.rb +29 -0
  155. data/app/subscribers/spree/report_subscriber.rb +26 -0
  156. data/config/locales/en.yml +126 -0
  157. data/db/migrate/20251110120000_create_spree_price_lists.rb +22 -0
  158. data/db/migrate/20251110120001_create_spree_price_rules.rb +13 -0
  159. data/db/migrate/20251110120002_add_price_list_id_to_spree_prices.rb +6 -0
  160. data/db/migrate/20251110120003_add_price_list_id_to_spree_line_items.rb +5 -0
  161. data/db/migrate/20251201172118_fix_indexes_on_friendly_id_slugs.rb +8 -0
  162. data/db/migrate/20251214000001_create_spree_webhook_endpoints.rb +19 -0
  163. data/db/migrate/20251214000002_create_spree_webhook_deliveries.rb +23 -0
  164. data/db/migrate/20251222000000_add_performance_indexes_to_spree_adjustments.rb +25 -0
  165. data/db/migrate/20260112000000_fix_spree_prices_unique_indexes.rb +33 -0
  166. data/db/migrate/20260115120000_create_spree_customer_groups.rb +14 -0
  167. data/db/migrate/20260115120001_create_spree_customer_group_users.rb +14 -0
  168. data/db/migrate/20260117140831_remove_not_null_constraint_from_policy_name.rb +5 -0
  169. data/db/migrate/20260118120000_add_statistics_to_store_products.rb +11 -0
  170. data/db/migrate/20260119120000_add_counter_caches_to_spree_products.rb +9 -0
  171. data/db/migrate/20260119170000_add_counter_caches_to_spree_taxons.rb +9 -0
  172. data/db/migrate/20260120120000_add_image_count_to_spree_variants.rb +9 -0
  173. data/lib/generators/spree/dummy/dummy_generator.rb +14 -2
  174. data/lib/spree/core/configuration.rb +1 -0
  175. data/lib/spree/core/controller_helpers/auth.rb +0 -15
  176. data/lib/spree/core/controller_helpers/currency.rb +13 -9
  177. data/lib/spree/core/controller_helpers/search.rb +1 -1
  178. data/lib/spree/core/controller_helpers/store.rb +5 -1
  179. data/lib/spree/core/engine.rb +61 -78
  180. data/lib/spree/core/importer/order.rb +1 -1
  181. data/lib/spree/core/importer/product.rb +1 -1
  182. data/lib/spree/core/preferences/preferable.rb +14 -1
  183. data/lib/spree/core/pricing/context.rb +63 -0
  184. data/lib/spree/core/pricing/resolver.rb +129 -0
  185. data/lib/spree/core/search/base.rb +1 -1
  186. data/lib/spree/core/token_generator.rb +1 -1
  187. data/lib/spree/core/version.rb +1 -1
  188. data/lib/spree/core.rb +42 -47
  189. data/lib/spree/events/adapters/active_support_notifications.rb +112 -0
  190. data/lib/spree/events/adapters/base.rb +193 -0
  191. data/lib/spree/events/registry.rb +99 -0
  192. data/lib/spree/events.rb +240 -0
  193. data/lib/spree/permitted_attributes.rb +13 -2
  194. data/lib/spree/testing_support/common_rake.rb +68 -35
  195. data/lib/spree/testing_support/factories/customer_group_factory.rb +6 -0
  196. data/lib/spree/testing_support/factories/customer_group_user_factory.rb +6 -0
  197. data/lib/spree/testing_support/factories/price_factory.rb +4 -0
  198. data/lib/spree/testing_support/factories/price_list_factory.rb +34 -0
  199. data/lib/spree/testing_support/factories/price_rule_factory.rb +49 -0
  200. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +12 -0
  201. data/lib/spree/testing_support/factories/stock_item_factory.rb +6 -4
  202. data/lib/spree/testing_support/factories/store_product_factory.rb +6 -0
  203. data/lib/spree/testing_support/factories/taxon_factory.rb +0 -1
  204. data/lib/spree/testing_support/factories/webhook_delivery_factory.rb +48 -0
  205. data/lib/spree/testing_support/factories/webhook_endpoint_factory.rb +22 -0
  206. data/lib/spree/testing_support/lifecycle_events.rb +38 -0
  207. data/lib/spree/testing_support/store.rb +4 -2
  208. data/lib/spree/webhooks.rb +22 -0
  209. data/lib/tasks/products.rake +40 -0
  210. data/lib/tasks/taxons.rake +19 -0
  211. data/lib/tasks/variants.rake +18 -0
  212. metadata +112 -114
  213. data/app/jobs/spree/themes/duplicate_components_job.rb +0 -59
  214. data/app/jobs/spree/themes/screenshot_job.rb +0 -81
  215. data/app/models/concerns/spree/has_page_links.rb +0 -53
  216. data/app/models/spree/page.rb +0 -188
  217. data/app/models/spree/page_block.rb +0 -73
  218. data/app/models/spree/page_blocks/buttons.rb +0 -29
  219. data/app/models/spree/page_blocks/heading.rb +0 -18
  220. data/app/models/spree/page_blocks/image.rb +0 -20
  221. data/app/models/spree/page_blocks/link.rb +0 -21
  222. data/app/models/spree/page_blocks/mega_nav.rb +0 -33
  223. data/app/models/spree/page_blocks/mega_nav_with_subcategories.rb +0 -32
  224. data/app/models/spree/page_blocks/metafields.rb +0 -18
  225. data/app/models/spree/page_blocks/nav.rb +0 -15
  226. data/app/models/spree/page_blocks/newsletter_form.rb +0 -18
  227. data/app/models/spree/page_blocks/products/brand.rb +0 -15
  228. data/app/models/spree/page_blocks/products/buy_buttons.rb +0 -24
  229. data/app/models/spree/page_blocks/products/description.rb +0 -18
  230. data/app/models/spree/page_blocks/products/price.rb +0 -18
  231. data/app/models/spree/page_blocks/products/quantity_selector.rb +0 -20
  232. data/app/models/spree/page_blocks/products/share.rb +0 -8
  233. data/app/models/spree/page_blocks/products/title.rb +0 -19
  234. data/app/models/spree/page_blocks/products/variant_picker.rb +0 -13
  235. data/app/models/spree/page_blocks/subheading.rb +0 -17
  236. data/app/models/spree/page_blocks/text.rb +0 -16
  237. data/app/models/spree/page_link.rb +0 -60
  238. data/app/models/spree/page_section.rb +0 -222
  239. data/app/models/spree/page_sections/announcement_bar.rb +0 -28
  240. data/app/models/spree/page_sections/breadcrumbs.rb +0 -12
  241. data/app/models/spree/page_sections/collection_banner.rb +0 -18
  242. data/app/models/spree/page_sections/custom_code.rb +0 -11
  243. data/app/models/spree/page_sections/featured_posts.rb +0 -45
  244. data/app/models/spree/page_sections/featured_product.rb +0 -50
  245. data/app/models/spree/page_sections/featured_taxon.rb +0 -90
  246. data/app/models/spree/page_sections/featured_taxons.rb +0 -45
  247. data/app/models/spree/page_sections/footer.rb +0 -101
  248. data/app/models/spree/page_sections/header.rb +0 -62
  249. data/app/models/spree/page_sections/image_banner.rb +0 -55
  250. data/app/models/spree/page_sections/image_with_text.rb +0 -65
  251. data/app/models/spree/page_sections/main_password_footer.rb +0 -18
  252. data/app/models/spree/page_sections/main_password_header.rb +0 -20
  253. data/app/models/spree/page_sections/newsletter.rb +0 -54
  254. data/app/models/spree/page_sections/page_title.rb +0 -19
  255. data/app/models/spree/page_sections/post_details.rb +0 -19
  256. data/app/models/spree/page_sections/post_grid.rb +0 -19
  257. data/app/models/spree/page_sections/product_details.rb +0 -53
  258. data/app/models/spree/page_sections/product_grid.rb +0 -13
  259. data/app/models/spree/page_sections/related_products.rb +0 -58
  260. data/app/models/spree/page_sections/rich_text.rb +0 -31
  261. data/app/models/spree/page_sections/taxon_banner.rb +0 -18
  262. data/app/models/spree/page_sections/taxon_grid.rb +0 -17
  263. data/app/models/spree/page_sections/video.rb +0 -107
  264. data/app/models/spree/pages/account.rb +0 -19
  265. data/app/models/spree/pages/cart.rb +0 -19
  266. data/app/models/spree/pages/checkout.rb +0 -15
  267. data/app/models/spree/pages/custom.rb +0 -38
  268. data/app/models/spree/pages/homepage.rb +0 -72
  269. data/app/models/spree/pages/login.rb +0 -19
  270. data/app/models/spree/pages/password.rb +0 -59
  271. data/app/models/spree/pages/post.rb +0 -27
  272. data/app/models/spree/pages/post_list.rb +0 -36
  273. data/app/models/spree/pages/product_details.rb +0 -30
  274. data/app/models/spree/pages/search_results.rb +0 -43
  275. data/app/models/spree/pages/shop_all.rb +0 -40
  276. data/app/models/spree/pages/taxon.rb +0 -29
  277. data/app/models/spree/pages/taxon_list.rb +0 -41
  278. data/app/models/spree/pages/wishlist.rb +0 -15
  279. data/app/models/spree/theme.rb +0 -233
  280. data/app/models/spree/themes/default.rb +0 -97
  281. data/app/services/spree/taxons/touch_featured_sections.rb +0 -21
  282. data/db/migrate/20250120094216_create_page_builder_models.rb +0 -78
  283. data/db/migrate/20250305121352_remove_page_builder_indices.rb +0 -11
  284. data/db/migrate/20250825175217_add_missing_page_builder_indexes.rb +0 -7
  285. data/db/migrate/20250913130044_add_page_links_counter_cache_to_spree_stores.rb +0 -10
  286. data/lib/generators/spree/dummy/templates/initializers/devise.rb +0 -3
  287. data/lib/generators/spree/install/install_generator.rb +0 -219
  288. data/lib/generators/spree/install/templates/config/initializers/spree.rb +0 -126
  289. data/lib/spree/core/webhooks.rb +0 -21
  290. data/lib/spree/testing_support/factories/page_block_factory.rb +0 -22
  291. data/lib/spree/testing_support/factories/page_factory.rb +0 -33
  292. data/lib/spree/testing_support/factories/page_link_factory.rb +0 -7
  293. data/lib/spree/testing_support/factories/page_section_factory.rb +0 -27
  294. data/lib/spree/testing_support/factories/theme_factory.rb +0 -14
@@ -1,59 +0,0 @@
1
- module Spree
2
- module Themes
3
- class DuplicateComponentsJob < Spree::BaseJob
4
- queue_as Spree.queues.themes
5
-
6
- # We need to duplicate:
7
- # 1. Theme files + sections with pageable_type Spree::Theme.
8
- # 2. Duplicate pages + sections.
9
- # 3. Adjust linkable on page links for Spree::PageSection and Spree::PageBlock parents and Spree::Page linkable.
10
-
11
- def perform(theme_id, duplicated_theme_id)
12
- theme = Spree::Theme.find(theme_id)
13
- duplicated_theme = Spree::Theme.find(duplicated_theme_id)
14
-
15
- ApplicationRecord.transaction do
16
- duplicated_pages = duplicate_pages(theme, duplicated_theme)
17
-
18
- # Duplicated links on pages and blocks have references to pages from the previous theme
19
- # We need to look for a duplicated page and update the link with it
20
- duplicate_layout_sections(theme, duplicated_theme)
21
- adjust_page_links(theme, duplicated_theme, duplicated_pages)
22
-
23
- duplicated_theme.update!(ready: true)
24
- end
25
- end
26
-
27
- private
28
-
29
- def duplicate_layout_sections(theme, duplicated_theme)
30
- theme.layout_sections.each { |section| section.deep_clone(duplicated_theme) }
31
- end
32
-
33
- def duplicate_pages(theme, duplicated_theme)
34
- theme.pages.map { |page| page.duplicate(duplicated_theme) }
35
- end
36
-
37
- def adjust_page_links(theme, duplicated_theme, duplicated_pages)
38
- page_sections = Spree::PageSection.where(pageable: duplicated_pages)
39
- layout_sections = duplicated_theme.layout_sections
40
- all_section_ids = page_sections.ids + layout_sections.ids
41
-
42
- all_page_blocks = Spree::PageBlock.where(section_id: all_section_ids)
43
-
44
- all_parent_ids = all_section_ids + all_page_blocks.ids
45
- all_page_links = Spree::PageLink.
46
- includes(:linkable, parent: :pageable).
47
- where(linkable_type: 'Spree::Page').
48
- where(parent_id: all_parent_ids, linkable_id: theme.pages)
49
-
50
- all_page_links.each do |page_link|
51
- linkable_type = page_link.linkable.type
52
- duplicated_page = duplicated_theme.pages.find_by(type: linkable_type)
53
-
54
- page_link.update!(linkable: duplicated_page)
55
- end
56
- end
57
- end
58
- end
59
- end
@@ -1,81 +0,0 @@
1
- require 'uri'
2
- require 'net/http'
3
-
4
- module Spree
5
- module Themes
6
- class ScreenshotJob < Spree::BaseJob
7
- queue_as Spree.queues.themes
8
-
9
- BASE_SCREENSHOT_API_URL = 'https://shot.screenshotapi.net/v3/screenshot'.freeze
10
- SCREENSHOT_OUTPUT = 'image'.freeze
11
- SCREENSHOT_FILE_TYPE = 'png'.freeze
12
-
13
- def perform(theme_id)
14
- theme = Spree::Theme.find(theme_id)
15
-
16
- Rails.logger.warn('Screenshot API token is missing') and return if screenshot_api_token.blank?
17
-
18
- return if theme.screenshot.attached?
19
-
20
- url = URI.encode_www_form_component("#{theme.store.url_or_custom_domain}?theme_id=#{theme_id}")
21
- query_params = {
22
- token: screenshot_api_token,
23
- url: url,
24
- output: SCREENSHOT_OUTPUT,
25
- file_type: SCREENSHOT_FILE_TYPE,
26
- retina: true,
27
- enable_caching: true
28
- }
29
- query = "#{BASE_SCREENSHOT_API_URL}?#{query_params.to_query}"
30
-
31
- # Send a GET request to the API
32
- uri = URI.parse(query)
33
- response = Net::HTTP.get_response(uri)
34
-
35
- case response.code
36
- when '301', '302'
37
- redirect_uri = response['location']
38
- redirect_uri = URI.parse(redirect_uri)
39
- response = Net::HTTP.get_response(redirect_uri)
40
- save_screenshot(theme, response)
41
- when '200'
42
- save_screenshot(theme, response)
43
- else
44
- Rails.error.report('Screenshot API returned non-200 status code')
45
- end
46
- end
47
-
48
- private
49
-
50
- def screenshot_api_token
51
- @screenshot_api_token ||= Spree.screenshot_api_token
52
- end
53
-
54
- def save_screenshot(theme, response)
55
- temp_file_path = "theme-screenshot-#{theme.id}.png"
56
-
57
- # Create a temporary file
58
- File.open(temp_file_path, "wb") do |file|
59
- file.write(response.body)
60
- end
61
-
62
- # Open the file for reading to attach it
63
- file = File.open(temp_file_path, "rb")
64
-
65
- # Attach the file
66
- theme.screenshot.attach(
67
- io: file,
68
- filename: "theme-screenshot-#{theme.id}.#{SCREENSHOT_FILE_TYPE}",
69
- content_type: "image/#{SCREENSHOT_FILE_TYPE}"
70
- )
71
- theme.save!
72
-
73
- # Close the file before attempting to delete it
74
- file.close
75
-
76
- # Remove the temporary file
77
- File.delete(temp_file_path) if File.exist?(temp_file_path)
78
- end
79
- end
80
- end
81
- end
@@ -1,53 +0,0 @@
1
- module Spree
2
- module HasPageLinks
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- has_many :links, -> { order(:position).includes(:linkable) }, class_name: 'Spree::PageLink', as: :parent, dependent: :destroy, inverse_of: :parent
7
- alias page_links links
8
-
9
- after_create :create_default_links, unless: :do_not_create_links
10
-
11
- attribute :do_not_create_links, :boolean, default: false
12
- attr_accessor :default_links
13
-
14
- def allowed_linkable_types
15
- [
16
- [Spree.t(:page), 'Spree::Page'],
17
- [Spree.t(:product), 'Spree::Product'],
18
- [Spree.t(:post), 'Spree::Post'],
19
- [Spree.t(:taxon), 'Spree::Taxon'],
20
- [Spree.t(:policy), 'Spree::Policy'],
21
- [Spree.t(:url), nil]
22
- ]
23
- end
24
-
25
- def default_linkable_type
26
- 'Spree::Page'
27
- end
28
-
29
- def theme_or_parent
30
- theme.preview? ? theme.parent : theme
31
- end
32
-
33
- def default_linkable_resource
34
- @default_linkable_resource ||= theme_or_parent.pages.find_by(type: 'Spree::Pages::Homepage')
35
- end
36
-
37
- def default_links
38
- @default_links.presence || []
39
- end
40
-
41
- def links_available?
42
- true
43
- end
44
-
45
- def create_default_links
46
- default_links.each do |link|
47
- link.parent = self
48
- link.save!
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,188 +0,0 @@
1
- module Spree
2
- class Page < Spree.base_class
3
- include Spree::Previewable
4
- include Spree::Linkable
5
-
6
- #
7
- # Magic methods
8
- #
9
- extend FriendlyId
10
- friendly_id :slug_candidates, use: [:slugged, :scoped, :history], scope: :pageable
11
- acts_as_paranoid
12
-
13
- #
14
- # Associations
15
- #
16
- belongs_to :pageable, polymorphic: true # this can be either Store or Theme
17
- has_many :sections, -> { order(position: :asc) }, class_name: 'Spree::PageSection', dependent: :destroy_async, as: :pageable
18
- alias page_sections sections
19
-
20
- #
21
- # Validations
22
- #
23
- validates :name, presence: true
24
- validates :pageable, presence: true
25
- validates :slug, uniqueness: { scope: :pageable, conditions: -> { where(deleted_at: nil).where.not(slug: nil) } }
26
-
27
- #
28
- # Callbacks
29
- #
30
- before_validation :set_name
31
- after_create :create_default_sections, unless: :duplicating
32
-
33
- #
34
- # Scopes
35
- #
36
- scope :linkable, lambda {
37
- where(type: [
38
- 'Spree::Pages::Homepage',
39
- 'Spree::Pages::ShopAll',
40
- 'Spree::Pages::PostList',
41
- 'Spree::Pages::Custom',
42
- 'Spree::Pages::Account',
43
- 'Spree::Pages::Login'
44
- ])
45
- }
46
- scope :product_details, -> { where(type: 'Spree::Pages::ProductDetails') }
47
- scope :standard, -> { where.not(type: 'Spree::Pages::Custom') }
48
- scope :custom, -> { where(type: 'Spree::Pages::Custom') }
49
-
50
- #
51
- # Virtual attributes
52
- #
53
- attribute :duplicating, :boolean, default: false
54
-
55
- def icon_name
56
- 'file-earmark-richtext'
57
- end
58
-
59
- def store
60
- if pageable.is_a?(Spree::Store)
61
- pageable
62
- else
63
- pageable.store
64
- end
65
- end
66
-
67
- def create_preview
68
- return self if preview? # no need to create a preview for the preview
69
-
70
- ActiveRecord::Base.connected_to(role: :writing) do
71
- ApplicationRecord.transaction do
72
- new_preview = dup
73
- new_preview.parent = self
74
- new_preview.duplicating = true
75
- new_preview.save!
76
-
77
- sections.includes(:links, { asset_attachment: :blob }, { blocks: [:rich_text_text, :links] }).each do |section|
78
- section.deep_clone(new_preview)
79
- end
80
-
81
- new_preview
82
- end
83
- end
84
- end
85
-
86
- # Promotes the page preview to the main page
87
- def promote
88
- return unless preview?
89
-
90
- ApplicationRecord.transaction do
91
- old_page = parent
92
- old_page.page_links.update_all(linkable_id: id)
93
- update(parent: nil) # clear reference to the old page
94
- Spree::Page.find(old_page.id).destroy # destroy the old page with their other previews, etc.
95
- end
96
- end
97
-
98
- def default_sections
99
- []
100
- end
101
-
102
- def customizable?
103
- false
104
- end
105
-
106
- def linkable?
107
- false
108
- end
109
-
110
- def layout_sections?
111
- true
112
- end
113
-
114
- def preview_url(theme_preview = nil, page_preview = nil)
115
- return if page_builder_url.blank?
116
-
117
- "#{page_builder_url}?#{url_query_params(theme_preview, page_preview).to_query}"
118
- end
119
-
120
- def display_name
121
- if custom?
122
- name
123
- else
124
- name.titleize
125
- end
126
- end
127
-
128
- def custom?
129
- type == 'Spree::Pages::Custom'
130
- end
131
-
132
- def duplicate(target_pageable)
133
- duplicated_page = dup
134
- duplicated_page.duplicating = true
135
- duplicated_page.pageable = target_pageable
136
- duplicated_page.save!
137
-
138
- sections_scope = sections.includes(:links, :blocks, { asset_attachment: :blob },
139
- { blocks: [:rich_text_text, :links, { asset_attachment: :blob }] })
140
- sections_scope.each { |section| section.deep_clone(duplicated_page) }
141
-
142
- duplicated_page
143
- end
144
-
145
- def theme
146
- @theme ||= if pageable.is_a?(Spree::Theme)
147
- pageable
148
- else
149
- pageable.default_theme
150
- end
151
- end
152
-
153
- private
154
-
155
- def create_default_sections
156
- default_sections.each do |section|
157
- section.pageable = self
158
- section.save!
159
- end
160
- end
161
-
162
- def url_query_params(theme_preview, page_preview)
163
- theme_preview_cache = theme_preview.updated_at.to_i.to_s + rand(999_999).to_s if theme_preview
164
-
165
- {
166
- theme_id: theme.id,
167
- page_preview_id: page_preview&.id,
168
- theme_preview_id: theme_preview&.id,
169
- theme_preview_cache: theme_preview_cache
170
- }
171
- end
172
-
173
- def set_name
174
- return if custom?
175
- return if name.present?
176
-
177
- self.name = self.class.name.demodulize
178
- end
179
-
180
- def should_generate_new_friendly_id?
181
- name_changed? && custom?
182
- end
183
-
184
- def page_builder_url_exists?(path)
185
- Spree::Core::Engine.routes.url_helpers.respond_to?(path)
186
- end
187
- end
188
- end
@@ -1,73 +0,0 @@
1
- module Spree
2
- class PageBlock < Spree.base_class
3
- include Spree::HasPageLinks
4
-
5
- #
6
- # Magic methods
7
- #
8
- acts_as_paranoid
9
- acts_as_list scope: :section
10
-
11
- #
12
- # Associations
13
- #
14
- belongs_to :section, class_name: 'Spree::PageSection', inverse_of: :blocks, touch: true
15
- delegate :store, :theme, to: :section
16
-
17
- #
18
- # Rich Text
19
- #
20
- has_rich_text :text
21
-
22
- #
23
- # Attachments
24
- #
25
- has_one_attached :asset, service: Spree.public_storage_service_name
26
-
27
- #
28
- # Validations
29
- #
30
- validates :section, :type, :name, presence: true
31
- validates :asset, content_type: Rails.application.config.active_storage.web_image_content_types
32
-
33
- #
34
- # Callbacks
35
- #
36
- before_validation :set_name_from_type, on: :create
37
-
38
- #
39
- # Preferences
40
- #
41
- TEXT_ALIGNMENT_DEFAULT = 'left'
42
- CONTAINER_ALIGNMENT_DEFAULT = 'left'
43
- SIZE_DEFAULT = 'medium'
44
- WIDTH_DESKTOP_DEFAULT = 100
45
- TOP_PADDING_DEFAULT = 0
46
- BOTTOM_PADDING_DEFAULT = 0
47
-
48
- preference :text_alignment, :string, default: -> { self.class::TEXT_ALIGNMENT_DEFAULT if defined?(self.class::TEXT_ALIGNMENT_DEFAULT) }
49
- preference :container_alignment, :string, default: -> { self.class::CONTAINER_ALIGNMENT_DEFAULT if defined?(self.class::CONTAINER_ALIGNMENT_DEFAULT) }
50
- preference :size, :string, default: -> { self.class::SIZE_DEFAULT if defined?(self.class::SIZE_DEFAULT) }
51
- preference :width_desktop, :integer, default: -> { self.class::WIDTH_DESKTOP_DEFAULT if defined?(self.class::WIDTH_DESKTOP_DEFAULT) }
52
- preference :top_padding, :integer, default: -> { self.class::TOP_PADDING_DEFAULT if defined?(self.class::TOP_PADDING_DEFAULT) }
53
- preference :bottom_padding, :integer, default: -> { self.class::BOTTOM_PADDING_DEFAULT if defined?(self.class::BOTTOM_PADDING_DEFAULT) }
54
-
55
- def display_name
56
- name
57
- end
58
-
59
- def form_partial_name
60
- type.demodulize.underscore
61
- end
62
-
63
- def icon_name
64
- 'fullscreen'
65
- end
66
-
67
- private
68
-
69
- def set_name_from_type
70
- self.name ||= type.demodulize.titleize
71
- end
72
- end
73
- end
@@ -1,29 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class Buttons < Spree::PageBlock
4
- include Spree::HasOneLink
5
-
6
- TEXT_ALIGNMENT_DEFAULT = 'center'
7
-
8
- preference :button_style_1, :string, default: 'primary'
9
- preference :background_color, :string
10
- preference :button_background_color, :string
11
- preference :button_text_color, :string
12
-
13
- # Without link there is no purpose of the button.
14
- def link_destroyed(_link)
15
- return unless page_links_count.zero?
16
-
17
- destroy
18
- end
19
-
20
- def display_name
21
- Spree.t('page_blocks.buttons.display_name')
22
- end
23
-
24
- def icon_name
25
- 'click'
26
- end
27
- end
28
- end
29
- end
@@ -1,18 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class Heading < Spree::PageBlock
4
- SIZE_DEFAULT = 'large'
5
-
6
- preference :text_color, :string
7
- preference :background_color, :string
8
-
9
- def icon_name
10
- 'heading'
11
- end
12
-
13
- def display_name
14
- text.to_plain_text.truncate(30)
15
- end
16
- end
17
- end
18
- end
@@ -1,20 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class Image < Spree::PageBlock
4
- include Spree::HasImageAltText
5
-
6
- alias image asset
7
-
8
- TOP_PADDING_DEFAULT = 20
9
- BOTTOM_PADDING_DEFAULT = 20
10
-
11
- preference :height, :integer, default: 64
12
- preference :mobile_height, :integer, default: 32
13
- preference :image_alt, :string
14
-
15
- def icon_name
16
- 'photo'
17
- end
18
- end
19
- end
20
- end
@@ -1,21 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class Link < Spree::PageBlock
4
- include Spree::HasOneLink
5
-
6
- def icon_name
7
- 'menu-2'
8
- end
9
-
10
- def display_name
11
- link&.label || Spree.t('page_blocks.link.display_name')
12
- end
13
-
14
- def link_destroyed(_link)
15
- return unless page_links_count.zero?
16
-
17
- destroy
18
- end
19
- end
20
- end
21
- end
@@ -1,33 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class MegaNav < Spree::PageBlock
4
- include Spree::HasPageLinks
5
-
6
- has_one :link, ->(ps) { ps.links.where(position: 1) }, class_name: 'Spree::PageLink', as: :parent, dependent: :destroy, inverse_of: :parent
7
- accepts_nested_attributes_for :link
8
-
9
- preference :featured_taxon_id, :string, default: ''
10
-
11
- def featured_taxon
12
- store.taxons.find_by(id: preferred_featured_taxon_id) if preferred_featured_taxon_id.present?
13
- end
14
-
15
- def icon_name
16
- 'layout-navbar-expand'
17
- end
18
-
19
- def display_name
20
- link&.label || Spree.t(:mega_nav)
21
- end
22
-
23
- def default_links
24
- @default_links.presence || [
25
- Spree::PageLink.new(
26
- label: Spree.t(:shop_all),
27
- linkable: theme_or_parent.pages.find_by(type: 'Spree::Pages::ShopAll')
28
- ),
29
- ]
30
- end
31
- end
32
- end
33
- end
@@ -1,32 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class MegaNavWithSubcategories < Spree::PageBlock
4
- preference :taxon_id, :string, default: ''
5
- preference :featured_taxon_id, :string, default: ''
6
-
7
- before_validation :make_taxon_id_valid
8
-
9
- def taxon
10
- store.taxons.find_by(id: preferred_taxon_id) if preferred_taxon_id.present?
11
- end
12
-
13
- def featured_taxon
14
- store.taxons.find_by(id: preferred_featured_taxon_id) if preferred_featured_taxon_id.present?
15
- end
16
-
17
- def icon_name
18
- 'category'
19
- end
20
-
21
- def display_name
22
- taxon&.name || Spree.t(:mega_nav_with_subcategories)
23
- end
24
-
25
- private
26
-
27
- def make_taxon_id_valid
28
- self.preferred_taxon_id = preferred_taxon_id.presence || store.taxons.where(depth: 1).first&.id
29
- end
30
- end
31
- end
32
- end
@@ -1,18 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class Metafields < Spree::PageBlock
4
- RESOURCE_TYPE_DEFAULT = 'Spree::Product'
5
-
6
- preference :resource_type, :string, default: -> { self.class::RESOURCE_TYPE_DEFAULT if defined?(self.class::RESOURCE_TYPE_DEFAULT) }
7
- preference :metafield_definition_ids, :array, default: -> { available_metafield_definitions.pluck(:id) }
8
-
9
- def icon_name
10
- 'list'
11
- end
12
-
13
- def available_metafield_definitions
14
- @available_metafield_definitions ||= Spree::MetafieldDefinition.where(resource_type: preferred_resource_type).available_on_front_end
15
- end
16
- end
17
- end
18
- end
@@ -1,15 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class Nav < Spree::PageBlock
4
- preference :label, :string, default: Spree.t('page_blocks.nav.label_default')
5
-
6
- def icon_name
7
- 'menu-2'
8
- end
9
-
10
- def display_name
11
- preferred_label
12
- end
13
- end
14
- end
15
- end
@@ -1,18 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- class NewsletterForm < Spree::PageBlock
4
- preference :button_text, :string, default: Spree.t('page_blocks.newsletter_form.button_text_default')
5
- preference :button_text_color, :string
6
- preference :button_background_color, :string
7
- preference :button_style, :string, default: 'primary'
8
- preference :placeholder, :string, default: Spree.t('page_blocks.newsletter_form.placeholder_default')
9
- preference :justify, :string, default: 'center'
10
-
11
- validates :preferred_button_style, inclusion: { in: ['primary', 'secondary'] }
12
-
13
- def icon_name
14
- 'forms'
15
- end
16
- end
17
- end
18
- end
@@ -1,15 +0,0 @@
1
- module Spree
2
- module PageBlocks
3
- module Products
4
- class Brand < Spree::PageBlocks::Heading
5
- preference :text_color, :string
6
-
7
- SIZE_DEFAULT = 'medium'
8
-
9
- def display_name
10
- Spree.t(:brand)
11
- end
12
- end
13
- end
14
- end
15
- end