diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index e445925e1d8..8490eafc27a 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -41,7 +41,7 @@ jobs: phpstan-result-cache- - name: PHPStan Static Analysis - run: XDEBUG_MODE=off php vendor/bin/phpstan.phar analyze + run: XDEBUG_MODE=off php vendor/bin/phpstan.phar analyze -c .phpstan.dist.openmage.neon - name: Save result cache uses: actions/cache/save@v4 diff --git a/.gitignore b/.gitignore index 77d3ebad40e..718075f5aa9 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ phpcs.xml # PhpStan .phpstan.cache +.phpstan.*.cache .phpstan*.neon phpstan*.neon !.phpstan.dist.neon diff --git a/.phpstan.dist.baseline.neon b/.phpstan.dist.baseline.neon index 2629281782e..c39444acd39 100644 --- a/.phpstan.dist.baseline.neon +++ b/.phpstan.dist.baseline.neon @@ -5322,6 +5322,18 @@ parameters: count: 1 path: app/design/adminhtml/default/default/template/api/user_roles_grid_js.phtml + - + message: '#^Variable \$roles might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/api/userroles.phtml + + - + message: '#^Variable \$user_roles might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/api/userroles.phtml + - message: '#^Call to protected method _isSelected\(\) of class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option\.$#' identifier: method.protected @@ -5418,6 +5430,24 @@ parameters: count: 1 path: app/design/adminhtml/default/default/template/catalog/product/price.phtml + - + message: '#^Variable \$_weeeTaxAttributes might not be defined\.$#' + identifier: variable.undefined + count: 9 + path: app/design/adminhtml/default/default/template/catalog/product/price.phtml + + - + message: '#^Variable \$addressCollection might not be defined\.$#' + identifier: variable.undefined + count: 4 + path: app/design/adminhtml/default/default/template/customer/tab/addresses.phtml + + - + message: '#^Variable \$customer might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/adminhtml/default/default/template/customer/tab/addresses.phtml + - message: '#^Call to an undefined method Mage_GiftMessage_Block_Message_Helper\:\:prepareAsIs\(\)\.$#' identifier: method.notFound @@ -5448,12 +5478,48 @@ parameters: count: 1 path: app/design/adminhtml/default/default/template/permissions/user_roles_grid_js.phtml + - + message: '#^Variable \$roles might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/permissions/userroles.phtml + + - + message: '#^Variable \$user_roles might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/permissions/userroles.phtml + + - + message: '#^Variable \$options might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/rating/options.phtml + - message: '#^Comparison operation "\>" between int\<1, max\> and 0 is always true\.$#' identifier: greater.alwaysTrue count: 1 path: app/design/adminhtml/default/default/template/report/grid.phtml + - + message: '#^Variable \$minAdminPasswordLength might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/resetforgottenpassword.phtml + + - + message: '#^Variable \$resetPasswordLinkToken might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/resetforgottenpassword.phtml + + - + message: '#^Variable \$userId might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/resetforgottenpassword.phtml + - message: '#^Method Mage_Adminhtml_Block_Sales_Order_Create_Abstract\:\:formatPrice\(\) invoked with 3 parameters, 1 required\.$#' identifier: arguments.count @@ -5472,6 +5538,12 @@ parameters: count: 1 path: app/design/adminhtml/default/default/template/sales/order/shipment/tracking/info.phtml + - + message: '#^Variable \$items might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/system/autocomplete.phtml + - message: '#^Access to protected property Mage_Adminhtml_Block_System_Config_Form_Field_Regexceptions\|Mage_CatalogInventory_Block_Adminhtml_Form_Field_Minsaleqty\:\:\$_addAfter\.$#' identifier: property.protected @@ -5514,6 +5586,66 @@ parameters: count: 2 path: app/design/adminhtml/default/default/template/system/store/tree.phtml + - + message: '#^Variable \$createUrl might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/class/add.phtml + + - + message: '#^Variable \$header might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/class/add.phtml + + - + message: '#^Variable \$form might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/class/save.phtml + + - + message: '#^Variable \$header might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/class/save.phtml + + - + message: '#^Variable \$createUrl might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/rule/add.phtml + + - + message: '#^Variable \$header might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/rule/add.phtml + + - + message: '#^Variable \$form might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/rule/save.phtml + + - + message: '#^Variable \$header might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/tax/toolbar/rule/save.phtml + + - + message: '#^Variable \$element might not be defined\.$#' + identifier: variable.undefined + count: 62 + path: app/design/adminhtml/default/default/template/widget/form/element.phtml + + - + message: '#^Variable \$formBlock might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/widget/form/element.phtml + - message: '#^Method Mage_Adminhtml_Block_Widget_Grid\:\:getEmptyCellColspan\(\) invoked with 1 parameter, 0 required\.$#' identifier: arguments.count @@ -5532,12 +5664,60 @@ parameters: count: 1 path: app/design/adminhtml/default/default/template/widget/grid/massaction.phtml + - + message: '#^Variable \$id might not be defined\.$#' + identifier: variable.undefined + count: 4 + path: app/design/adminhtml/default/default/template/widget/tabsleft.phtml + + - + message: '#^Variable \$sections might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/default/template/widget/tabsleft.phtml + + - + message: '#^Variable \$minAdminPasswordLength might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/adminhtml/default/openmage/template/resetforgottenpassword.phtml + + - + message: '#^Variable \$resetPasswordLinkToken might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/openmage/template/resetforgottenpassword.phtml + + - + message: '#^Variable \$userId might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/adminhtml/default/openmage/template/resetforgottenpassword.phtml + + - + message: '#^Variable \$_weeeTaxAttributes might not be defined\.$#' + identifier: variable.undefined + count: 8 + path: app/design/frontend/base/default/template/bundle/catalog/product/price.phtml + - message: '#^Method Mage_Catalog_Block_Product_Abstract\:\:getTierPrices\(\) invoked with 2 parameters, 0\-1 required\.$#' identifier: arguments.count count: 1 path: app/design/frontend/base/default/template/bundle/catalog/product/view/option_tierprices.phtml + - + message: '#^Variable \$_weeeTaxAttributes might not be defined\.$#' + identifier: variable.undefined + count: 9 + path: app/design/frontend/base/default/template/bundle/catalog/product/view/option_tierprices.phtml + + - + message: '#^Variable \$_weeeTaxAttributes might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/bundle/catalog/product/view/price.phtml + - message: '#^Call to protected method _isSelected\(\) of class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option\.$#' identifier: method.protected @@ -5592,6 +5772,36 @@ parameters: count: 1 path: app/design/frontend/base/default/template/bundle/catalog/product/view/type/bundle/options.phtml + - + message: '#^Variable \$_weeeTaxAttributes might not be defined\.$#' + identifier: variable.undefined + count: 8 + path: app/design/frontend/base/default/template/bundle/rss/catalog/product/price.phtml + + - + message: '#^Variable \$_item might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/bundle/sales/order/creditmemo/items/renderer.phtml + + - + message: '#^Variable \$_showlastRow might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/bundle/sales/order/creditmemo/items/renderer.phtml + + - + message: '#^Variable \$_item might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/bundle/sales/order/invoice/items/renderer.phtml + + - + message: '#^Variable \$_showlastRow might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/bundle/sales/order/invoice/items/renderer.phtml + - message: '#^Call to method escapeUrl\(\) on an unknown class Mage_Catalog_Block_Layer_Filter\.$#' identifier: class.notFound @@ -5670,6 +5880,12 @@ parameters: count: 1 path: app/design/frontend/base/default/template/catalog/product/view/options/type/text.phtml + - + message: '#^Variable \$_weeeTaxAttributes might not be defined\.$#' + identifier: variable.undefined + count: 9 + path: app/design/frontend/base/default/template/catalog/product/view/tierprices.phtml + - message: '#^Method Mage_Checkout_Helper_Data\:\:formatPrice\(\) invoked with 3 parameters, 1 required\.$#' identifier: arguments.count @@ -5694,12 +5910,24 @@ parameters: count: 1 path: app/design/frontend/base/default/template/checkout/cart/sidebar/default.phtml + - + message: '#^Variable \$this might not be defined\.$#' + identifier: variable.undefined + count: 45 + path: app/design/frontend/base/default/template/checkout/cart/sidebar/default.phtml + - message: '#^Left side of && is always true\.$#' identifier: booleanAnd.leftAlwaysTrue count: 1 path: app/design/frontend/base/default/template/checkout/multishipping/address/select.phtml + - + message: '#^Variable \$this might not be defined\.$#' + identifier: variable.undefined + count: 7 + path: app/design/frontend/base/default/template/checkout/multishipping/item/default.phtml + - message: '#^Parameter \#1 \$totals of method Mage_Checkout_Block_Multishipping_Overview\:\:renderTotals\(\) expects Mage_Sales_Model_Order_Total, array\ given\.$#' identifier: argument.type @@ -5760,6 +5988,72 @@ parameters: count: 1 path: app/design/frontend/base/default/template/checkout/total/nominal.phtml + - + message: '#^Variable \$pageData might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/cms/content.phtml + + - + message: '#^Variable \$pageData might not be defined\.$#' + identifier: variable.undefined + count: 4 + path: app/design/frontend/base/default/template/cms/meta.phtml + + - + message: '#^Variable \$html might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/core/messages.phtml + + - + message: '#^Variable \$types might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/core/messages.phtml + + - + message: '#^Variable \$customer might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/customer/balance.phtml + + - + message: '#^Variable \$action might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/customer/form/address.phtml + + - + message: '#^Variable \$address might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/customer/form/address.phtml + + - + message: '#^Variable \$countries might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/customer/form/address.phtml + + - + message: '#^Variable \$data might not be defined\.$#' + identifier: variable.undefined + count: 12 + path: app/design/frontend/base/default/template/customer/form/address.phtml + + - + message: '#^Variable \$primaryTypes might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/customer/form/address.phtml + + - + message: '#^Variable \$action might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/customer/form/changepassword.phtml + - message: '#^Cannot call method isEnabled\(\) on Mage_Core_Block_Abstract\|false\.$#' identifier: method.nonObject @@ -5772,6 +6066,24 @@ parameters: count: 3 path: app/design/frontend/base/default/template/customer/form/register.phtml + - + message: '#^Variable \$orders might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/customer/orders.phtml + + - + message: '#^Variable \$wishlist might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/customer/wishlist.phtml + + - + message: '#^Variable \$currency might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/directory/currency/switch.phtml + - message: '#^Method Mage_Checkout_Helper_Data\:\:formatPrice\(\) invoked with 3 parameters, 1 required\.$#' identifier: arguments.count @@ -5790,6 +6102,24 @@ parameters: count: 12 path: app/design/frontend/base/default/template/downloadable/checkout/onepage/review/item.phtml + - + message: '#^Variable \$this might not be defined\.$#' + identifier: variable.undefined + count: 16 + path: app/design/frontend/base/default/template/email/order/items/creditmemo/default.phtml + + - + message: '#^Variable \$this might not be defined\.$#' + identifier: variable.undefined + count: 16 + path: app/design/frontend/base/default/template/email/order/items/invoice/default.phtml + + - + message: '#^Variable \$this might not be defined\.$#' + identifier: variable.undefined + count: 8 + path: app/design/frontend/base/default/template/email/order/items/shipment/default.phtml + - message: '#^Cannot call method getMessage\(\) on string\.$#' identifier: method.nonObject @@ -5820,6 +6150,84 @@ parameters: count: 1 path: app/design/frontend/base/default/template/googleanalytics/ga.phtml + - + message: '#^Variable \$crumbs might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/html/breadcrumbs.phtml + + - + message: '#^Variable \$toplinks might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/html/top.links.phtml + + - + message: '#^Variable \$am might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$days might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$defaultFormat might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$enUS might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$firstDay might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$months might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$pm might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$today might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$toolTipFormat might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$week might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + + - + message: '#^Variable \$weekendDays might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/base/default/template/page/js/calendar.phtml + - message: '#^Class Mage_Paypal_Block_Express_Form referenced with incorrect case\: Mage_PayPal_Block_Express_Form\.$#' identifier: class.nameCase @@ -5850,6 +6258,12 @@ parameters: count: 3 path: app/design/frontend/base/default/template/persistent/customer/form/register.phtml + - + message: '#^Variable \$data might not be defined\.$#' + identifier: variable.undefined + count: 3 + path: app/design/frontend/base/default/template/review/form.phtml + - message: '#^Parameter \#1 \(non\-empty\-array\) of echo cannot be converted to string\.$#' identifier: echo.nonString @@ -6042,6 +6456,12 @@ parameters: count: 1 path: app/design/frontend/rwd/default/template/checkout/cart/sidebar/default.phtml + - + message: '#^Variable \$this might not be defined\.$#' + identifier: variable.undefined + count: 45 + path: app/design/frontend/rwd/default/template/checkout/cart/sidebar/default.phtml + - message: '#^Parameter \#1 \$totals of method Mage_Checkout_Block_Multishipping_Overview\:\:renderTotals\(\) expects Mage_Sales_Model_Order_Total, array\ given\.$#' identifier: argument.type @@ -6060,6 +6480,42 @@ parameters: count: 12 path: app/design/frontend/rwd/default/template/checkout/onepage/review/item.phtml + - + message: '#^Variable \$action might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/rwd/default/template/customer/form/address.phtml + + - + message: '#^Variable \$address might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: app/design/frontend/rwd/default/template/customer/form/address.phtml + + - + message: '#^Variable \$countries might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/rwd/default/template/customer/form/address.phtml + + - + message: '#^Variable \$data might not be defined\.$#' + identifier: variable.undefined + count: 12 + path: app/design/frontend/rwd/default/template/customer/form/address.phtml + + - + message: '#^Variable \$primaryTypes might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/rwd/default/template/customer/form/address.phtml + + - + message: '#^Variable \$action might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/frontend/rwd/default/template/customer/form/changepassword.phtml + - message: '#^Cannot call method isEnabled\(\) on Mage_Core_Block_Abstract\|false\.$#' identifier: method.nonObject @@ -6114,6 +6570,18 @@ parameters: count: 3 path: app/design/frontend/rwd/default/template/persistent/customer/form/register.phtml + - + message: '#^Variable \$data might not be defined\.$#' + identifier: variable.undefined + count: 3 + path: app/design/frontend/rwd/default/template/review/form.phtml + + - + message: '#^Variable \$steps might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: app/design/install/default/default/template/install/state.phtml + - message: '#^Comparison operation "\>\=" between int\<0, max\> and 0 is always true\.$#' identifier: greaterOrEqual.alwaysTrue diff --git a/.phpstan.dist.neon b/.phpstan.dist.neon index ac155db64d8..17ba380437e 100644 --- a/.phpstan.dist.neon +++ b/.phpstan.dist.neon @@ -7,140 +7,6 @@ parameters: min: 80100 max: 80499 magentoRootPath: %currentWorkingDirectory% - fileExtensions: - - php - - phtml - paths: - - api.php - - cron.php - - get.php - - index.php - - install.php - - app/Mage.php - - app/code/core/Mage - - app/design/ - - errors - - lib/Mage - - lib/Magento - - lib/Varien - - shell - - tests/unit - excludePaths: - #incompatible interfaces - - app/code/core/Mage/Admin/Model/Acl/Assert/Ip.php - - app/code/core/Mage/Admin/Model/Acl/Assert/Time.php - - app/code/core/Mage/Api/Model/Acl/Assert/Ip.php - - app/code/core/Mage/Api/Model/Acl/Assert/Time.php - - app/code/core/Mage/Core/Model/Mysql4/Design/Theme/Collection.php - - lib/Varien/Directory/Collection.php - - lib/Varien/Directory/Factory.php - - lib/Varien/File/Object.php - - # deprecated _getHelper() - - app/code/core/Mage/Adminhtml/Controller/Rss/Abstract.php - - app/code/core/Mage/Adminhtml/controllers/Rss/OrderController.php - - app/code/core/Mage/Adminhtml/controllers/Rss/CatalogController.php - - # contains 1 abstract method and must therefore be declared abstract or implement the remaining methods - - app/code/core/Mage/Dataflow/Model/Session/Adapter/Http.php - - app/code/core/Mage/Dataflow/Model/Convert/Iterator/Http.php - - app/code/core/Mage/Dataflow/Model/Convert/Iterator/File/Csv.php - - lib/Varien/Convert/Validator/Column.php - - # Cannot declare class Varien_Date, because the name is already in use - - app/code/core/Mage/Catalog/Model/Product/Option/Type/Date.php - - # Cannot declare class XMLParser, because the name is already in use - - app/code/core/Mage/Centinel/Model/Api.php - - app/code/core/Mage/Centinel/Model/Api/Client.php - - # Class phpseclib\Net\SSH2 not found. - - app/code/core/Mage/Paypal/Model/Report/Settlement.php - - lib/Varien/Io/Sftp.php - - # Dataflow/Model/Convert/Iterator.php - - app/code/core/Mage/Dataflow/Model/Convert/Iterator.php - - # Too much noise from "Variable $this might not be defined" - - app/code/core/*/*/data/* - - app/code/core/*/*/sql/* - - # requires Mycrypt - - lib/Magento/Crypt.php - - lib/Varien/Crypt/Mcrypt.php - - # Instantiated class not found - - lib/Varien/Image/Adapter.php - ignoreErrors: - - - # @todo remove unused classes/template - # @todo add classes to widgets - message: '#^Variable \$this might not be defined\.$#' - paths: - - app/design/adminhtml/default/default/template/api/usernroles.phtml - - app/design/adminhtml/default/default/template/dashboard/searches.phtml - - app/design/adminhtml/default/default/template/dashboard/store/switcher.phtml - - app/design/adminhtml/default/default/template/empty.phtml - - app/design/adminhtml/default/default/template/overlay_popup.phtml - - app/design/adminhtml/default/default/template/popup.phtml - - app/design/adminhtml/default/default/template/promo/form.phtml - - app/design/adminhtml/default/default/template/rating/stars/detailed.phtml - - app/design/adminhtml/default/default/template/review/add.phtml - - app/design/adminhtml/default/default/template/sales/billing/agreement/form.phtml - - app/design/adminhtml/default/default/template/sales/items/renderer/default.phtml - - app/design/adminhtml/default/default/template/sales/order/shipment/create/items/renderer/configurable.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/discount.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/due.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/footer.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/grand.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/item.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/main.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/paid.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/refunded.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/shipping.phtml - - app/design/adminhtml/default/default/template/sales/order/totals/subtotal.phtml - - app/design/adminhtml/default/default/template/sales/order/view/tracking.phtml - - app/design/adminhtml/default/default/template/system/info.phtml - - app/design/adminhtml/default/default/template/tax/class/page/edit.phtml - - app/design/adminhtml/default/default/template/tax/toolbar/class/save.phtml - - app/design/adminhtml/default/default/template/tax/toolbar/rule/save.phtml - - app/design/frontend/base/default/template/bundle/catalog/product/list/partof.phtml - - app/design/frontend/base/default/template/bundle/catalog/product/view/options/notice.phtml - - app/design/frontend/base/default/template/catalog/category/page.phtml - - app/design/frontend/base/default/template/catalog/category/widget/link/link_block.phtml - - app/design/frontend/base/default/template/catalog/category/widget/link/link_inline.phtml - - app/design/frontend/base/default/template/catalog/product/view/price.phtml - - app/design/frontend/base/default/template/catalog/product/widget/link/link_block.phtml - - app/design/frontend/base/default/template/catalog/product/widget/link/link_inline.phtml - - app/design/frontend/base/default/template/checkout/cart/render/default.phtml - - app/design/frontend/base/default/template/checkout/cart/render/simple.phtml - - app/design/frontend/base/default/template/cms/widget/link/link_block.phtml - - app/design/frontend/base/default/template/cms/widget/link/link_inline.phtml - - app/design/frontend/base/default/template/cms/widget/static_block/default.phtml - - app/design/frontend/base/default/template/core/messages.phtml - - app/design/frontend/base/default/template/customer/address.phtml - - app/design/frontend/base/default/template/customer/balance.phtml - - app/design/frontend/base/default/template/customer/form/address.phtml - - app/design/frontend/base/default/template/customer/form/changepassword.phtml - - app/design/frontend/base/default/template/customer/orders.phtml - - app/design/frontend/base/default/template/customer/wishlist.phtml - - app/design/frontend/base/default/template/directory/currency/switch.phtml - - app/design/frontend/base/default/template/page/redirect.phtml - - app/design/frontend/base/default/template/paypal/hss/review/button.phtml - - app/design/frontend/rwd/default/template/checkout/cart/render/default.phtml - - app/design/frontend/rwd/default/template/checkout/cart/render/simple.phtml - - app/design/frontend/rwd/default/template/customer/form/address.phtml - - app/design/frontend/rwd/default/template/customer/form/changepassword.phtml - - app/design/frontend/rwd/default/template/paypal/express/review/address.phtml - - app/design/install/default/default/template/page.phtml - - - identifier: phpunit.coversMethod - - - identifier: variable.undefined - paths: - - app/design/*/*/template/* - - errors/* - - lib/Varien/* tmpDir: .phpstan.cache level: 5 checkFunctionNameCase: true diff --git a/.phpstan.dist.openmage.neon b/.phpstan.dist.openmage.neon new file mode 100644 index 00000000000..b6a8cf1e5d2 --- /dev/null +++ b/.phpstan.dist.openmage.neon @@ -0,0 +1,138 @@ +includes: + - .phpstan.dist.neon +parameters: + fileExtensions: + - php + - phtml + paths: + - api.php + - cron.php + - get.php + - index.php + - install.php + - app/Mage.php + - app/code/core/Mage + - app/design/ + - errors + - lib/Mage + - lib/Magento + - lib/Varien + - shell + excludePaths: + #incompatible interfaces + - app/code/core/Mage/Admin/Model/Acl/Assert/Ip.php + - app/code/core/Mage/Admin/Model/Acl/Assert/Time.php + - app/code/core/Mage/Api/Model/Acl/Assert/Ip.php + - app/code/core/Mage/Api/Model/Acl/Assert/Time.php + - app/code/core/Mage/Core/Model/Mysql4/Design/Theme/Collection.php + - lib/Varien/Directory/Collection.php + - lib/Varien/Directory/Factory.php + - lib/Varien/File/Object.php + + # deprecated _getHelper() + - app/code/core/Mage/Adminhtml/Controller/Rss/Abstract.php + - app/code/core/Mage/Adminhtml/controllers/Rss/OrderController.php + - app/code/core/Mage/Adminhtml/controllers/Rss/CatalogController.php + + # contains 1 abstract method and must therefore be declared abstract or implement the remaining methods + - app/code/core/Mage/Dataflow/Model/Session/Adapter/Http.php + - app/code/core/Mage/Dataflow/Model/Convert/Iterator/Http.php + - app/code/core/Mage/Dataflow/Model/Convert/Iterator/File/Csv.php + - lib/Varien/Convert/Validator/Column.php + + # Cannot declare class Varien_Date, because the name is already in use + - app/code/core/Mage/Catalog/Model/Product/Option/Type/Date.php + + # Cannot declare class XMLParser, because the name is already in use + - app/code/core/Mage/Centinel/Model/Api.php + - app/code/core/Mage/Centinel/Model/Api/Client.php + + # Class phpseclib\Net\SSH2 not found. + - app/code/core/Mage/Paypal/Model/Report/Settlement.php + - lib/Varien/Io/Sftp.php + + # Dataflow/Model/Convert/Iterator.php + - app/code/core/Mage/Dataflow/Model/Convert/Iterator.php + + # Too much noise from "Variable $this might not be defined" + - app/code/core/*/*/data/* + - app/code/core/*/*/sql/* + + # requires Mycrypt + - lib/Magento/Crypt.php + - lib/Varien/Crypt/Mcrypt.php + + # Instantiated class not found + - lib/Varien/Image/Adapter.php + ignoreErrors: + - + identifier: variable.undefined + paths: + - errors/* + - lib/Varien/* + - + # @todo remove unused classes/template + # @todo add classes to widgets + message: '#^Variable \$this might not be defined\.$#' + paths: + - app/design/adminhtml/default/default/template/api/usernroles.phtml + - app/design/adminhtml/default/default/template/dashboard/searches.phtml + - app/design/adminhtml/default/default/template/dashboard/store/switcher.phtml + - app/design/adminhtml/default/default/template/empty.phtml + - app/design/adminhtml/default/default/template/overlay_popup.phtml + - app/design/adminhtml/default/default/template/popup.phtml + - app/design/adminhtml/default/default/template/promo/form.phtml + - app/design/adminhtml/default/default/template/rating/stars/detailed.phtml + - app/design/adminhtml/default/default/template/review/add.phtml + - app/design/adminhtml/default/default/template/sales/billing/agreement/form.phtml + - app/design/adminhtml/default/default/template/sales/items/renderer/default.phtml + - app/design/adminhtml/default/default/template/sales/order/shipment/create/items/renderer/configurable.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/discount.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/due.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/footer.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/grand.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/item.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/main.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/paid.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/refunded.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/shipping.phtml + - app/design/adminhtml/default/default/template/sales/order/totals/subtotal.phtml + - app/design/adminhtml/default/default/template/sales/order/view/tracking.phtml + - app/design/adminhtml/default/default/template/system/info.phtml + - app/design/adminhtml/default/default/template/tax/class/page/edit.phtml + - app/design/adminhtml/default/default/template/tax/toolbar/class/save.phtml + - app/design/adminhtml/default/default/template/tax/toolbar/rule/save.phtml + - app/design/frontend/base/default/template/bundle/catalog/product/list/partof.phtml + - app/design/frontend/base/default/template/bundle/catalog/product/view/options/notice.phtml + - app/design/frontend/base/default/template/catalog/category/page.phtml + - app/design/frontend/base/default/template/catalog/category/widget/link/link_block.phtml + - app/design/frontend/base/default/template/catalog/category/widget/link/link_inline.phtml + - app/design/frontend/base/default/template/catalog/product/view/price.phtml + - app/design/frontend/base/default/template/catalog/product/widget/link/link_block.phtml + - app/design/frontend/base/default/template/catalog/product/widget/link/link_inline.phtml + - app/design/frontend/base/default/template/checkout/cart/render/default.phtml + - app/design/frontend/base/default/template/checkout/cart/render/simple.phtml + - app/design/frontend/base/default/template/cms/widget/link/link_block.phtml + - app/design/frontend/base/default/template/cms/widget/link/link_inline.phtml + - app/design/frontend/base/default/template/cms/widget/static_block/default.phtml + - app/design/frontend/base/default/template/core/messages.phtml + - app/design/frontend/base/default/template/customer/address.phtml + - app/design/frontend/base/default/template/customer/balance.phtml + - app/design/frontend/base/default/template/customer/form/address.phtml + - app/design/frontend/base/default/template/customer/form/changepassword.phtml + - app/design/frontend/base/default/template/customer/orders.phtml + - app/design/frontend/base/default/template/customer/wishlist.phtml + - app/design/frontend/base/default/template/directory/currency/switch.phtml + - app/design/frontend/base/default/template/page/redirect.phtml + - app/design/frontend/base/default/template/paypal/hss/review/button.phtml + - app/design/frontend/rwd/default/template/checkout/cart/render/default.phtml + - app/design/frontend/rwd/default/template/checkout/cart/render/simple.phtml + - app/design/frontend/rwd/default/template/checkout/multishipping/item/default.phtml + - app/design/frontend/rwd/default/template/customer/form/address.phtml + - app/design/frontend/rwd/default/template/customer/form/changepassword.phtml + - app/design/frontend/rwd/default/template/downloadable/checkout/cart/item/default.phtml + - app/design/frontend/rwd/default/template/email/order/items/creditmemo/default.phtml + - app/design/frontend/rwd/default/template/email/order/items/invoice/default.phtml + - app/design/frontend/rwd/default/template/email/order/items/shipment/default.phtml + - app/design/frontend/rwd/default/template/paypal/express/review/address.phtml + - app/design/install/default/default/template/page.phtml diff --git a/.phpstan.dist.phpunit.neon b/.phpstan.dist.phpunit.neon new file mode 100644 index 00000000000..f0603919abf --- /dev/null +++ b/.phpstan.dist.phpunit.neon @@ -0,0 +1,32 @@ +includes: + - .phpstan.dist.neon +parameters: + fileExtensions: + - php + paths: + - errors + - tests/unit + tmpDir: .phpstan.phpunit.cache + level: 7 + ignoreErrors: + - + message: '#^Cannot call method [a-zA-Z0-9]+\(\) on Mage_Core_Block_Abstract\|false.#' + - + identifier: missingType.iterableValue + - + identifier: phpunit.coversMethod + - + identifier: argument.type + path: tests/unit/Mage/Reports/Model/Resource/Report/CollectionTest.php + - + identifier: argument.type + path: errors/processor.php + - + identifier: missingType.parameter + path: errors/processor.php + - + identifier: missingType.return + path: errors/processor.php + - + identifier: return.type + path: errors/processor.php diff --git a/app/code/core/Mage/Admin/Model/Block.php b/app/code/core/Mage/Admin/Model/Block.php index 4db6952bfdb..f3979efb2c4 100644 --- a/app/code/core/Mage/Admin/Model/Block.php +++ b/app/code/core/Mage/Admin/Model/Block.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Class Mage_Admin_Model_Block * @@ -29,6 +32,8 @@ */ class Mage_Admin_Model_Block extends Mage_Core_Model_Abstract { + public const BLOCK_NAME_REGEX = '/^[-_a-zA-Z0-9]+\/[-_a-zA-Z0-9\/]+$/'; + /** * Initialize variable model */ @@ -40,31 +45,46 @@ protected function _construct() /** * @return array|true * @throws Exception - * @throws Zend_Validate_Exception */ public function validate() { - $errors = []; + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); - if (!Zend_Validate::is($this->getBlockName(), 'NotEmpty')) { - $errors[] = Mage::helper('adminhtml')->__('Block Name is required field.'); - } - $disallowedBlockNames = Mage::helper('admin/block')->getDisallowedBlockNames(); - if (in_array($this->getBlockName(), $disallowedBlockNames)) { - $errors[] = Mage::helper('adminhtml')->__('Block Name is disallowed.'); - } - if (!Zend_Validate::is($this->getBlockName(), 'Regex', ['/^[-_a-zA-Z0-9]+\/[-_a-zA-Z0-9\/]+$/'])) { - $errors[] = Mage::helper('adminhtml')->__('Block Name is incorrect.'); - } + $violations[] = $validator->validate($this->getBlockName(), [ + new Assert\NotBlank([ + 'message' => Mage::helper('adminhtml')->__('Block Name is required field.'), + ]), + new Assert\Regex([ + 'pattern' => self::BLOCK_NAME_REGEX, + 'message' => Mage::helper('adminhtml')->__('Block Name is incorrect.'), + ]), + new Assert\Choice([ + 'choices' => Mage::helper('admin/block')->getDisallowedBlockNames(), + 'match' => false, + 'message' => Mage::helper('adminhtml')->__('Block Name is disallowed.'), + ]), + ]); + + $violations[] = $validator->validate($this->getIsAllowed(), [ + new Assert\Choice([ + 'choices' => ['0', '1'], + 'message' => Mage::helper('adminhtml')->__('Is Allowed is required field.'), + ]), + ]); - if (!in_array($this->getIsAllowed(), ['0', '1'])) { - $errors[] = Mage::helper('adminhtml')->__('Is Allowed is required field.'); + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } } - if (empty($errors)) { + if (count($errors) === 0) { return true; } - return $errors; + + return (array) $errors; } /** diff --git a/app/code/core/Mage/Admin/Model/User.php b/app/code/core/Mage/Admin/Model/User.php index 9655a4af4e9..4bde36dc006 100644 --- a/app/code/core/Mage/Admin/Model/User.php +++ b/app/code/core/Mage/Admin/Model/User.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Admin user model * @@ -579,26 +582,38 @@ public function getStartupPageUrl() * Returns TRUE or array of errors. * * @return array|true - * @throws Zend_Validate_Exception */ public function validate() { - $errors = new ArrayObject(); - - if (!Zend_Validate::is($this->getUsername(), 'NotEmpty')) { - $errors->append(Mage::helper('adminhtml')->__('User Name is required field.')); - } - - if (!Zend_Validate::is($this->getFirstname(), 'NotEmpty')) { - $errors->append(Mage::helper('adminhtml')->__('First Name is required field.')); - } - - if (!Zend_Validate::is($this->getLastname(), 'NotEmpty')) { - $errors->append(Mage::helper('adminhtml')->__('Last Name is required field.')); - } + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); + + $violations[] = $validator->validate($this->getUsername(), [new Assert\NotBlank([ + 'message' => Mage::helper('adminhtml')->__('User Name is required field.'), + ])]); + + $violations[] = $validator->validate($this->getFirstname(), [new Assert\NotBlank([ + 'message' => Mage::helper('adminhtml')->__('First Name is required field.'), + ])]); + + $violations[] = $validator->validate($this->getLastname(), [new Assert\NotBlank([ + 'message' => Mage::helper('adminhtml')->__('Last Name is required field.'), + ])]); + + $violations[] = $validator->validate($this->getEmail(), [ + new Assert\NotBlank([ + 'message' => Mage::helper('adminhtml')->__('Please enter a valid email.'), + ]), + new Assert\Email([ + 'message' => Mage::helper('adminhtml')->__('Please enter a valid email.'), + ]), + ]); - if (!Zend_Validate::is($this->getEmail(), 'EmailAddress')) { - $errors->append(Mage::helper('adminhtml')->__('Please enter a valid email.')); + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } } if ($this->hasNewPassword()) { @@ -608,18 +623,31 @@ public function validate() } if (isset($password)) { $minAdminPasswordLength = $this->getMinAdminPasswordLength(); - if (Mage::helper('core/string')->strlen($password) < $minAdminPasswordLength) { - $errors->append(Mage::helper('adminhtml') - ->__('Password must be at least of %d characters.', $minAdminPasswordLength)); - } + $violations = []; + $violations[] = $validator->validate($password, [ + new Assert\Length([ + 'min' => $minAdminPasswordLength, + 'minMessage' => Mage::helper('adminhtml')->__('Password must be at least of %d characters.', $minAdminPasswordLength), + ]), + new Assert\Regex([ + 'pattern' => '/^(?=.*[a-z])(?=.*[0-9]).+$/iu', + 'message' => Mage::helper('adminhtml')->__('Password must include both numeric and alphabetic characters.'), + ]), + ]); - if (!preg_match('/[a-z]/iu', $password) || !preg_match('/[0-9]/u', $password)) { - $errors->append(Mage::helper('adminhtml') - ->__('Password must include both numeric and alphabetic characters.')); + if ($this->hasPasswordConfirmation()) { + $violations[] = $validator->validate($this->getPasswordConfirmation(), [ + new Assert\IdenticalTo([ + 'value' => $password, + 'message' => Mage::helper('adminhtml')->__('Password confirmation must be same as password.'), + ]), + ]); } - if ($this->hasPasswordConfirmation() && $password != $this->getPasswordConfirmation()) { - $errors->append(Mage::helper('adminhtml')->__('Password confirmation must be same as password.')); + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } } Mage::dispatchEvent('admin_user_validate', [ @@ -645,13 +673,14 @@ public function validate() * * @param string $password * @return array|true - * @throws Zend_Validate_Exception + * @throws Exception */ public function validateCurrentPassword($password) { + $validator = Validation::createValidator(); $result = []; - if (!Zend_Validate::is($password, 'NotEmpty')) { + if ($validator->validate($password, [new Assert\NotBlank()])->count() > 0) { $result[] = $this->_getHelper('adminhtml')->__('Current password field cannot be empty.'); } elseif (is_null($this->getId()) || !Mage::helper('core')->validateHash($password, $this->getPassword())) { $result[] = $this->_getHelper('adminhtml')->__('Invalid current password.'); diff --git a/app/code/core/Mage/Admin/Model/Variable.php b/app/code/core/Mage/Admin/Model/Variable.php index ef8906dc555..49c1bd1499a 100644 --- a/app/code/core/Mage/Admin/Model/Variable.php +++ b/app/code/core/Mage/Admin/Model/Variable.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Class Mage_Admin_Model_Variable * @@ -38,29 +41,41 @@ protected function _construct() } /** - * @return array|bool + * @return array|true * @throws Exception - * @throws Zend_Validate_Exception */ public function validate() { - $errors = []; + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); - if (!Zend_Validate::is($this->getVariableName(), 'NotEmpty')) { - $errors[] = Mage::helper('adminhtml')->__('Variable Name is required field.'); - } - if (!Zend_Validate::is($this->getVariableName(), 'Regex', ['/^[-_a-zA-Z0-9\/]*$/'])) { - $errors[] = Mage::helper('adminhtml')->__('Variable Name is incorrect.'); - } + $violations[] = $validator->validate($this->getVariableName(), [ + new Assert\NotBlank([ + 'message' => Mage::helper('adminhtml')->__('Variable Name is required field.'), + ]), + new Assert\Regex([ + 'message' => Mage::helper('adminhtml')->__('Variable Name is incorrect.'), + 'pattern' => '/^[-_a-zA-Z0-9\/]*$/', + ]), + ]); - if (!in_array($this->getIsAllowed(), ['0', '1'])) { - $errors[] = Mage::helper('adminhtml')->__('Is Allowed is required field.'); + $violations[] = $validator->validate($this->getIsAllowed(), [new Assert\Choice([ + 'choices' => ['0', '1'], + 'message' => Mage::helper('adminhtml')->__('Is Allowed is required field.'), + ])]); + + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } } - if (empty($errors)) { + if (count($errors) === 0) { return true; } - return $errors; + + return (array) $errors; } /** diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Email/Address.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Email/Address.php index 660602860aa..3d11e6a3042 100644 --- a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Email/Address.php +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Email/Address.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * System config email field backend model * @@ -22,11 +25,15 @@ */ class Mage_Adminhtml_Model_System_Config_Backend_Email_Address extends Mage_Core_Model_Config_Data { + /** + * @throws Mage_Core_Exception + */ protected function _beforeSave() { - $value = $this->getValue(); - if (!Zend_Validate::is($value, 'EmailAddress')) { - Mage::throwException(Mage::helper('adminhtml')->__('Invalid email address "%s".', $value)); + $email = $this->getValue(); + $validator = Validation::createValidator(); + if ($validator->validate($email, [new Assert\NotBlank(), new Assert\Email()])->count() > 0) { + Mage::throwException(Mage::helper('adminhtml')->__('Invalid email address "%s".', $email)); } return $this; } diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php index 40e1487c5f4..cd72da7aa1c 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Catalog product attribute controller * @@ -207,8 +210,10 @@ public function saveAction() //validate attribute_code if (isset($data['attribute_code'])) { - $validatorAttrCode = new Zend_Validate_Regex(['pattern' => '/^(?!event$)[a-z][a-z_0-9]{1,254}$/']); - if (!$validatorAttrCode->isValid($data['attribute_code'])) { + $validator = Validation::createValidator(); + if ($validator->validate($data['attribute_code'], new Assert\Regex([ + 'pattern' => '/^(?!event$)[a-z][a-z_0-9]{1,254}$/', + ]))->count() > 0) { $session->addError( Mage::helper('catalog')->__('Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter. Do not use "event" for an attribute code.'), ); diff --git a/app/code/core/Mage/Adminhtml/controllers/IndexController.php b/app/code/core/Mage/Adminhtml/controllers/IndexController.php index 121305613f8..8237d03ce00 100644 --- a/app/code/core/Mage/Adminhtml/controllers/IndexController.php +++ b/app/code/core/Mage/Adminhtml/controllers/IndexController.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Index admin controller * @@ -220,7 +223,8 @@ public function forgotpasswordAction() if ($this->_validateFormKey()) { if (!empty($email)) { // Validate received data to be an email address - if (Zend_Validate::is($email, 'EmailAddress')) { + $validator = Validation::createValidator(); + if ($validator->validate($email, [new Assert\NotBlank(), new Assert\Email()])->count() === 0) { $collection = Mage::getResourceModel('admin/user_collection'); /** @var Mage_Admin_Model_Resource_User_Collection $collection */ $collection->addFieldToFilter('email', $email); diff --git a/app/code/core/Mage/Api/Model/User.php b/app/code/core/Mage/Api/Model/User.php index f9d76f1487f..58712dd7ff2 100644 --- a/app/code/core/Mage/Api/Model/User.php +++ b/app/code/core/Mage/Api/Model/User.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Api model * @@ -365,27 +368,33 @@ protected function _getHelper($helperName) * Validate user attribute values. * * @return array|true - * @throws Zend_Validate_Exception */ public function validate() { + $validator = Validation::createValidator(); + $violations = []; $errors = new ArrayObject(); - if (!Zend_Validate::is($this->getUsername(), 'NotEmpty')) { - $errors->append($this->_getHelper('api')->__('User Name is required field.')); - } + $violations[] = $validator->validate($this->getUsername(), [new Assert\NotBlank([ + 'message' => Mage::helper('api')->__('User Name is required field.'), + ])]); - if (!Zend_Validate::is($this->getFirstname(), 'NotEmpty')) { - $errors->append($this->_getHelper('api')->__('First Name is required field.')); - } + $violations[] = $validator->validate($this->getFirstname(), [new Assert\NotBlank([ + 'message' => Mage::helper('api')->__('First Name is required field.'), + ])]); - if (!Zend_Validate::is($this->getLastname(), 'NotEmpty')) { - $errors->append($this->_getHelper('api')->__('Last Name is required field.')); - } + $violations[] = $validator->validate($this->getLastname(), [new Assert\NotBlank([ + 'message' => Mage::helper('api')->__('Last Name is required field.'), + ])]); - if (!Zend_Validate::is($this->getEmail(), 'EmailAddress')) { - $errors->append($this->_getHelper('api')->__('Please enter a valid email.')); - } + $violations[] = $validator->validate($this->getEmail(), [ + new Assert\NotBlank([ + 'message' => Mage::helper('adminhtml')->__('Please enter a valid email.'), + ]), + new Assert\Email([ + 'message' => Mage::helper('adminhtml')->__('Please enter a valid email.'), + ]), + ]); if ($this->hasNewApiKey()) { $apiKey = $this->getNewApiKey(); @@ -395,18 +404,35 @@ public function validate() if (isset($apiKey)) { $minCustomerPasswordLength = $this->_getMinCustomerPasswordLength(); - if (strlen($apiKey) < $minCustomerPasswordLength) { - $errors->append($this->_getHelper('api') - ->__('Api Key must be at least of %d characters.', $minCustomerPasswordLength)); - } + $violations[] = $validator->validate($apiKey, [ + new Assert\Length([ + 'min' => $minCustomerPasswordLength, + 'minMessage' => $this->_getHelper('api') + ->__('Api Key must be at least of %d characters.', $minCustomerPasswordLength), + ]), + new Assert\Regex([ + 'pattern' => '/[a-z]/iu', + 'message' => $this->_getHelper('api') + ->__('Api Key must include both numeric and alphabetic characters.'), + ]), + new Assert\Regex([ + 'pattern' => '/[0-9]/u', + 'message' => $this->_getHelper('api') + ->__('Api Key must include both numeric and alphabetic characters.'), + ]), + ]); - if (!preg_match('/[a-z]/iu', $apiKey) || !preg_match('/[0-9]/u', $apiKey)) { - $errors->append($this->_getHelper('api') - ->__('Api Key must include both numeric and alphabetic characters.')); + if ($this->hasApiKeyConfirmation()) { + $violations[] = $validator->validate($apiKey, [new Assert\IdenticalTo([ + 'value' => $this->getApiKeyConfirmation(), + 'message' => $this->_getHelper('api')->__('Api Key confirmation must be same as Api Key.'), + ])]); } + } - if ($this->hasApiKeyConfirmation() && $apiKey != $this->getApiKeyConfirmation()) { - $errors->append($this->_getHelper('api')->__('Api Key confirmation must be same as Api Key.')); + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); } } diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Validator/Product.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Validator/Product.php index 146c4ac545d..6e9d5527b82 100644 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Validator/Product.php +++ b/app/code/core/Mage/Catalog/Model/Api2/Product/Validator/Product.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * API2 catalog_product Validator * @@ -122,18 +125,20 @@ public function isValidData(array $data) * * @param array $data * @param Mage_Eav_Model_Entity_Type $productEntity + * @throws Mage_Api2_Exception */ protected function _validateAttributes($data, $productEntity) { - if (!isset($data['attribute_set_id']) || empty($data['attribute_set_id'])) { + if (empty($data['attribute_set_id'])) { $this->_critical('Missing "attribute_set_id" in request.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); } - if (!isset($data['type_id']) || empty($data['type_id'])) { + if (empty($data['type_id'])) { $this->_critical('Missing "type_id" in request.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); } // Validate weight - if (isset($data['weight']) && !empty($data['weight']) && $data['weight'] > 0 - && !Zend_Validate::is($data['weight'], 'Between', [0, self::MAX_DECIMAL_VALUE]) + $validator = Validation::createValidator(); + if (!empty($data['weight']) && $data['weight'] > 0 + && $validator->validate($data['weight'], new Assert\Range(['min' => 0, 'max' => self::MAX_DECIMAL_VALUE]))->count() > 0 ) { $this->_addError('The "weight" value is not within the specified range.'); } @@ -278,8 +283,11 @@ protected function _validateSku($data) if ($this->_isUpdate() && !isset($data['sku'])) { return true; } - if (!Zend_Validate::is((string) $data['sku'], 'StringLength', ['min' => 0, 'max' => 64])) { - $this->_addError('SKU length should be 64 characters maximum.'); + + $skuMaxLength = Mage_Eav_Model_Entity_Attribute::ATTRIBUTE_CODE_MAX_LENGTH; + $validator = Validation::createValidator(); + if ($validator->validate($data['sku'], new Assert\Length(['max' => $skuMaxLength]))->count() > 0) { + $this->_addError(sprintf('SKU length should be %d characters maximum.', $skuMaxLength)); } } diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Type/Default.php b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Default.php index 1ac1af5364b..60ace10b27f 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Option/Type/Default.php +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Default.php @@ -28,7 +28,7 @@ * @method $this setQuoteItem(Mage_Sales_Model_Quote_Item $value) * @method array|int getUserValue() * @method $this setRequest(Varien_Object $value) - * @method $this setUserValue(array|int $value) + * @method $this setUserValue(array|int|null $value) */ class Mage_Catalog_Model_Product_Option_Type_Default extends Varien_Object { diff --git a/app/code/core/Mage/Checkout/Model/Type/Onepage.php b/app/code/core/Mage/Checkout/Model/Type/Onepage.php index 3ff917162cb..9e642d5b804 100644 --- a/app/code/core/Mage/Checkout/Model/Type/Onepage.php +++ b/app/code/core/Mage/Checkout/Model/Type/Onepage.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * One page checkout processing model * @@ -506,7 +509,8 @@ protected function _processValidateCustomer(Mage_Sales_Model_Quote_Address $addr } } elseif (self::METHOD_GUEST == $this->getQuote()->getCheckoutMethod()) { $email = $address->getData('email'); - if (!Zend_Validate::is($email, 'EmailAddress')) { + $validator = Validation::createValidator(); + if ($validator->validate($email, [new Assert\NotBlank(), new Assert\Email()])->count() > 0) { return [ 'error' => -1, 'message' => Mage::helper('checkout')->__('Invalid email address "%s"', $email), diff --git a/app/code/core/Mage/Contacts/controllers/IndexController.php b/app/code/core/Mage/Contacts/controllers/IndexController.php index e1b0bd802ca..db98b2dbae4 100644 --- a/app/code/core/Mage/Contacts/controllers/IndexController.php +++ b/app/code/core/Mage/Contacts/controllers/IndexController.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Contacts index controller * @@ -72,17 +75,21 @@ public function postAction() $postObject = new Varien_Object(); $postObject->setData($post); - // check data - $error = false; - if (!Zend_Validate::is(trim($post['name']), 'NotEmpty')) { - $error = true; - } elseif (!Zend_Validate::is(trim($post['comment']), 'NotEmpty')) { - $error = true; - } elseif (!Zend_Validate::is(trim($post['email']), 'EmailAddress')) { - $error = true; + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); + + $violations[] = $validator->validate(trim($post['name']), [new Assert\NotBlank()]); + $violations[] = $validator->validate(trim($post['comment']), [new Assert\NotBlank()]); + $violations[] = $validator->validate(trim($post['email']), [new Assert\NotBlank(), new Assert\Email()]); + + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } } - if ($error) { + if (count($errors) !== 0) { Mage::throwException($this->__('Unable to submit your request. Please, try again later')); } diff --git a/app/code/core/Mage/Core/Model/App.php b/app/code/core/Mage/Core/Model/App.php index 73aaad31ec5..5b36043e363 100644 --- a/app/code/core/Mage/Core/Model/App.php +++ b/app/code/core/Mage/Core/Model/App.php @@ -973,7 +973,7 @@ public function getDistroLocaleCode() /** * Retrieve application website object * - * @param null|Mage_Core_Model_Website|true|int|string $id + * @param null|Mage_Core_Model_Website|bool|int|string $id * @return Mage_Core_Model_Website */ public function getWebsite($id = null) diff --git a/app/code/core/Mage/Core/Model/Email/Queue.php b/app/code/core/Mage/Core/Model/Email/Queue.php index 31a0848d031..e8983b21708 100644 --- a/app/code/core/Mage/Core/Model/Email/Queue.php +++ b/app/code/core/Mage/Core/Model/Email/Queue.php @@ -35,8 +35,8 @@ * @method string getMessageBody() * @method $this setMessageBody(string $value) * @method $this setMessageBodyHash(string $value) - * @method string getMessageParameters() - * @method $this setMessageParameters(string $value) + * @method array getMessageParameters() + * @method $this setMessageParameters(array $value) * @method $this setProcessedAt(string $value) */ class Mage_Core_Model_Email_Queue extends Mage_Core_Model_Abstract diff --git a/app/code/core/Mage/Core/Model/Email/Template/Abstract.php b/app/code/core/Mage/Core/Model/Email/Template/Abstract.php index f68c917dfa2..18d3289b8d0 100644 --- a/app/code/core/Mage/Core/Model/Email/Template/Abstract.php +++ b/app/code/core/Mage/Core/Model/Email/Template/Abstract.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Template model * @@ -228,9 +231,8 @@ protected function _getCssFileContent($filename) '_theme' => $theme, ], ); - $validator = new Zend_Validate_File_Extension('css'); - if ($validator->isValid($filePath) && is_readable($filePath)) { + if ($this->validateFileExension($filePath, 'css') && is_readable($filePath)) { return (string) file_get_contents($filePath); } @@ -238,6 +240,20 @@ protected function _getCssFileContent($filename) return ''; } + public function validateFileExension(string $filePath, string $extension): bool + { + $validator = Validation::createValidator(); + + if ($extension === 'css') { + $extension = ['css' => ['text/css', 'text/plain']]; + } + + return $validator->validate($filePath, new Assert\File([ + 'maxSize' => '8M', + 'extensions' => $extension, + ]))->count() === 0; + } + /** * Accepts a path to a System Config setting that contains a comma-delimited list of files to load. Loads those * files and then returns the concatenated content. diff --git a/app/code/core/Mage/Core/Model/Variable.php b/app/code/core/Mage/Core/Model/Variable.php index aafe18fb243..9a6faf506de 100644 --- a/app/code/core/Mage/Core/Model/Variable.php +++ b/app/code/core/Mage/Core/Model/Variable.php @@ -105,7 +105,7 @@ public function getValue($type = null) /** * Validation of object data. Checking for unique variable code * - * @return bool | string + * @return true|string */ public function validate() { diff --git a/app/code/core/Mage/Customer/Model/Address/Abstract.php b/app/code/core/Mage/Customer/Model/Address/Abstract.php index e8737b5f46e..559de65ea2c 100644 --- a/app/code/core/Mage/Customer/Model/Address/Abstract.php +++ b/app/code/core/Mage/Customer/Model/Address/Abstract.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Address abstract model * @@ -450,39 +453,48 @@ public function validate() */ protected function _basicCheck() { - if (!Zend_Validate::is($this->getFirstname(), 'NotEmpty')) { - $this->addError(Mage::helper('customer')->__('Please enter the first name.')); - } + $validator = Validation::createValidator(); + $violations = []; - if (!Zend_Validate::is($this->getLastname(), 'NotEmpty')) { - $this->addError(Mage::helper('customer')->__('Please enter the last name.')); - } + $violations[] = $validator->validate($this->getFirstname(), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('Please enter the first name.'), + ])]); - if (!Zend_Validate::is($this->getStreet(1), 'NotEmpty')) { - $this->addError(Mage::helper('customer')->__('Please enter the street.')); - } + $violations[] = $validator->validate($this->getLastname(), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('Please enter the last name.'), + ])]); - if (!Zend_Validate::is($this->getCity(), 'NotEmpty')) { - $this->addError(Mage::helper('customer')->__('Please enter the city.')); - } + $violations[] = $validator->validate($this->getStreet(1), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('Please enter the street.'), + ])]); + + $violations[] = $validator->validate($this->getCity(), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('Please enter the city.'), + ])]); - if (!Zend_Validate::is($this->getTelephone(), 'NotEmpty')) { - $this->addError(Mage::helper('customer')->__('Please enter the telephone number.')); + $violations[] = $validator->validate($this->getTelephone(), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('Please enter the telephone number.'), + ])]); + + foreach ($violations as $violation) { + foreach ($violation as $error) { + $this->addError($error->getMessage()); + } } $havingOptionalZip = Mage::helper('directory')->getCountriesWithOptionalZip(); if (!in_array($this->getCountryId(), $havingOptionalZip) - && !Zend_Validate::is($this->getPostcode(), 'NotEmpty') + && $validator->validate($this->getPostcode(), [new Assert\NotBlank()])->count() > 0 ) { $this->addError(Mage::helper('customer')->__('Please enter the zip/postal code.')); } - if (!Zend_Validate::is($this->getCountryId(), 'NotEmpty')) { + if ($validator->validate($this->getCountryId(), [new Assert\NotBlank()])->count() > 0) { $this->addError(Mage::helper('customer')->__('Please enter the country.')); } if ($this->getCountryModel()->getRegionCollection()->getSize() - && !Zend_Validate::is($this->getRegionId(), 'NotEmpty') + && $validator->validate($this->getRegionId(), [new Assert\NotBlank()])->count() > 0 && Mage::helper('directory')->isRegionRequired($this->getCountryId()) ) { $this->addError(Mage::helper('customer')->__('Please enter the state/province.')); diff --git a/app/code/core/Mage/Customer/Model/Customer.php b/app/code/core/Mage/Customer/Model/Customer.php index 4dcf9b2c926..2d39500d06e 100644 --- a/app/code/core/Mage/Customer/Model/Customer.php +++ b/app/code/core/Mage/Customer/Model/Customer.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Customer model * @@ -1040,91 +1043,141 @@ public function setStore(Mage_Core_Model_Store $store) * * @return array|true * @throws Mage_Core_Exception - * @throws Zend_Validate_Exception */ public function validate() { - $errors = []; - if (!Zend_Validate::is(trim($this->getFirstname()), 'NotEmpty')) { - $errors[] = Mage::helper('customer')->__('The first name cannot be empty.'); - } - - if (!Zend_Validate::is(trim($this->getLastname()), 'NotEmpty')) { - $errors[] = Mage::helper('customer')->__('The last name cannot be empty.'); - } - - if (!Zend_Validate::is($this->getEmail(), 'EmailAddress')) { - $errors[] = Mage::helper('customer')->__('Invalid email address "%s".', $this->getEmail()); - } + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); + + $violations[] = $validator->validate($this->getFirstname(), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('The first name cannot be empty.'), + ])]); + + $violations[] = $validator->validate($this->getLastname(), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('The last name cannot be empty.'), + ])]); + + $email = $this->getEmail(); + $violations[] = $validator->validate($email, [ + new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('Invalid email address "%s".', $email), + ]), + new Assert\Email([ + 'message' => Mage::helper('customer')->__('Invalid email address "%s".', $email), + ]), + ]); $password = $this->getPassword(); - if (!$this->getId() && !Zend_Validate::is($password, 'NotEmpty')) { - $errors[] = Mage::helper('customer')->__('The password cannot be empty.'); - } $minPasswordLength = $this->getMinPasswordLength(); - if (strlen($password) && !Zend_Validate::is($password, 'StringLength', [$minPasswordLength])) { - $errors[] = Mage::helper('customer') - ->__('The minimum password length is %s', $minPasswordLength); - } - if (strlen($password) && !Zend_Validate::is($password, 'StringLength', ['max' => self::MAXIMUM_PASSWORD_LENGTH])) { - $errors[] = Mage::helper('customer') - ->__('Please enter a password with at most %s characters.', self::MAXIMUM_PASSWORD_LENGTH); - } + $violations[] = $validator->validate($password, [ + new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('The password cannot be empty.'), + ]), + new Assert\Length([ + 'min' => $minPasswordLength, + 'minMessage' => Mage::helper('customer')->__( + 'The minimum password length is %s', + $minPasswordLength, + ), + 'max' => self::MAXIMUM_PASSWORD_LENGTH, + 'maxMessage' => Mage::helper('customer')->__( + 'Please enter a password with at most %s characters.', + self::MAXIMUM_PASSWORD_LENGTH, + ), + ]), + ]); + $confirmation = $this->getPasswordConfirmation(); - if ($password != $confirmation) { - $errors[] = Mage::helper('customer')->__('Please make sure your passwords match.'); - } + $violations[] = $validator->validate($confirmation, [ + new Assert\IdenticalTo([ + 'value' => $password, + 'message' => Mage::helper('customer')->__('Please make sure your passwords match.'), + ]), + ]); $entityType = Mage::getSingleton('eav/config')->getEntityType('customer'); - $attribute = Mage::getModel('customer/attribute')->loadByCode($entityType, 'dob'); - if ($attribute->getIsRequired() && trim($this->getDob()) == '') { - $errors[] = Mage::helper('customer')->__('The Date of Birth is required.'); + + if ($this->shouldValidateDob($entityType)) { + $violations[] = $validator->validate(trim($this->getDob()), [new Assert\Date(), new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('The Date of Birth is required.'), + ])]); } - $attribute = Mage::getModel('customer/attribute')->loadByCode($entityType, 'taxvat'); - if ($attribute->getIsRequired() && trim($this->getTaxvat()) == '') { - $errors[] = Mage::helper('customer')->__('The TAX/VAT number is required.'); + + if ($this->shouldValidateTaxvat($entityType)) { + $violations[] = $validator->validate(trim($this->getTaxvat()), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('The TAX/VAT number is required.'), + ])]); } - $attribute = Mage::getModel('customer/attribute')->loadByCode($entityType, 'gender'); - if ($attribute->getIsRequired() && trim($this->getGender()) == '') { - $errors[] = Mage::helper('customer')->__('Gender is required.'); + + if ($this->shouldValidateGender($entityType)) { + $violations[] = $validator->validate(trim($this->getGender()), [new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('Gender is required.'), + ])]); } - if (empty($errors)) { + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } + } + + if (count($errors) === 0) { return true; } - return $errors; + + return (array) $errors; } /** * Validate customer password on reset * @return array|true - * @throws Zend_Validate_Exception */ public function validateResetPassword() { - $errors = []; + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); + $password = $this->getPassword(); - if (!Zend_Validate::is($password, 'NotEmpty')) { - $errors[] = Mage::helper('customer')->__('The password cannot be empty.'); - } $minPasswordLength = $this->getMinPasswordLength(); - if (!Zend_Validate::is($password, 'StringLength', [$minPasswordLength])) { - $errors[] = Mage::helper('customer') - ->__('The minimum password length is %s', $minPasswordLength); - } - if (!Zend_Validate::is($password, 'StringLength', ['max' => self::MAXIMUM_PASSWORD_LENGTH])) { - $errors[] = Mage::helper('customer') - ->__('Please enter a password with at most %s characters.', self::MAXIMUM_PASSWORD_LENGTH); - } - $confirmation = $this->getPasswordConfirmation(); - if ($password != $confirmation) { - $errors[] = Mage::helper('customer')->__('Please make sure your passwords match.'); + + $violations[] = $validator->validate($password, [ + new Assert\NotBlank([ + 'message' => Mage::helper('customer')->__('The password cannot be empty.'), + ]), + new Assert\Length([ + 'min' => $minPasswordLength, + 'minMessage' => Mage::helper('customer')->__( + 'The minimum password length is %s', + $minPasswordLength, + ), + 'max' => self::MAXIMUM_PASSWORD_LENGTH, + 'maxMessage' => Mage::helper('customer')->__( + 'Please enter a password with at most %s characters.', + self::MAXIMUM_PASSWORD_LENGTH, + ), + ]), + ]); + + $violations[] = $validator->validate($this->getPasswordConfirmation(), [ + new Assert\IdenticalTo([ + 'value' => $password, + 'message' => Mage::helper('customer')->__('Please make sure your passwords match.'), + ]), + ]); + + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } } - if (empty($errors)) { + if (count($errors) === 0) { return true; } - return $errors; + + return (array) $errors; } /** @@ -1670,4 +1723,38 @@ public function getMinPasswordLength() $absoluteMinLength = Mage_Core_Model_App::ABSOLUTE_MIN_PASSWORD_LENGTH; return ($minLength < $absoluteMinLength) ? $absoluteMinLength : $minLength; } + + /** + * @throws Mage_Core_Exception + */ + public function shouldValidateDob($entityType): bool + { + $attribute = $this->getCustomerAttributeModel()->loadByCode($entityType, 'dob'); + return $attribute->getIsRequired(); + } + + /** + * @throws Mage_Core_Exception + */ + public function shouldValidateGender($entityType): bool + { + $attribute = $this->getCustomerAttributeModel()->loadByCode($entityType, 'gender'); + return $attribute->getIsRequired(); + } + + /** + * @throws Mage_Core_Exception + */ + public function shouldValidateTaxvat($entityType): bool + { + $attribute = $this->getCustomerAttributeModel()->loadByCode($entityType, 'taxvat'); + return $attribute->getIsRequired(); + } + + public function getCustomerAttributeModel(): Mage_Customer_Model_Attribute + { + /** @var Mage_Customer_Model_Attribute $model */ + $model = Mage::getModel('customer/attribute'); + return $model; + } } diff --git a/app/code/core/Mage/Customer/controllers/AccountController.php b/app/code/core/Mage/Customer/controllers/AccountController.php index 2828dd62847..88b71edc88a 100644 --- a/app/code/core/Mage/Customer/controllers/AccountController.php +++ b/app/code/core/Mage/Customer/controllers/AccountController.php @@ -15,6 +15,8 @@ */ use Mage_Customer_Helper_Data as Helper; +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; /** * Customer account controller @@ -722,6 +724,7 @@ public function forgotPasswordAction() /** * Forgot customer password action * @throws Mage_Core_Model_Store_Exception + * @throws Mage_Core_Exception */ public function forgotPasswordPostAction() { @@ -743,7 +746,8 @@ public function forgotPasswordPostAction() return; } - if (!Zend_Validate::is($email, 'EmailAddress')) { + $validator = Validation::createValidator(); + if ($validator->validate($email, [new Assert\NotBlank(), new Assert\Email()])->count() > 0) { $this->_getSession()->setForgottenEmail($email); $this->_getSession()->addError($this->__('Invalid email address.')); $this->_redirect('*/*/forgotpassword'); diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute.php b/app/code/core/Mage/Eav/Model/Entity/Attribute.php index 8e2d97718eb..8ef935ab408 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * EAV Entity attribute model * @@ -138,18 +141,16 @@ public function loadEntityAttributeIdBySet() * * @inheritDoc * @throws Mage_Eav_Exception + * @throws Mage_Core_Exception */ protected function _beforeSave() { - /** + /* * Check for maximum attribute_code length */ - if (isset($this->_data['attribute_code']) && - !Zend_Validate::is( - $this->_data['attribute_code'], - 'StringLength', - ['max' => self::ATTRIBUTE_CODE_MAX_LENGTH], - ) + $validator = Validation::createValidator(); + if (isset($this->_data['attribute_code']) + && $validator->validate($this->_data['attribute_code'], [new Assert\Length(['max' => self::ATTRIBUTE_CODE_MAX_LENGTH])])->count() > 0 ) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Maximum length of attribute code must be less then %s symbols', self::ATTRIBUTE_CODE_MAX_LENGTH)); } diff --git a/app/code/core/Mage/Eav/Model/Entity/Setup.php b/app/code/core/Mage/Eav/Model/Entity/Setup.php index c54ff152114..5b9bb58649b 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Setup.php +++ b/app/code/core/Mage/Eav/Model/Entity/Setup.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * EAV Entity Setup Model * @@ -639,15 +642,17 @@ protected function _prepareValues($attr) * Validate attribute data before insert into table * * @param array $data - * @throws Mage_Eav_Exception * @return true + * @throws Mage_Core_Exception + * @throws Mage_Eav_Exception */ protected function _validateAttributeData($data) { $attributeCodeMaxLength = Mage_Eav_Model_Entity_Attribute::ATTRIBUTE_CODE_MAX_LENGTH; + $validator = Validation::createValidator(); - if (isset($data['attribute_code']) && - !Zend_Validate::is($data['attribute_code'], 'StringLength', ['max' => $attributeCodeMaxLength]) + if (isset($data['attribute_code']) + && $validator->validate($data['attribute_code'], new Assert\Length(['max' => $attributeCodeMaxLength]))->count() > 0 ) { throw Mage::exception( 'Mage_Eav', diff --git a/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php b/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php index a5c96958c06..837ffd4eb84 100644 --- a/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php +++ b/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Import entity customer model * @@ -612,7 +615,8 @@ public function validateRow(array $rowData, $rowNum) $this->addRowError(self::ERROR_EMAIL_SITE_NOT_FOUND, $rowNum); } } elseif (self::SCOPE_DEFAULT == $rowScope) { // row is SCOPE_DEFAULT = new customer block begins - if (!Zend_Validate::is($email, 'EmailAddress')) { + $validator = Validation::createValidator(); + if ($validator->validate($email, [new Assert\NotBlank(), new Assert\Email()])->count() > 0) { $this->addRowError(self::ERROR_INVALID_EMAIL, $rowNum); } elseif (!isset($this->_websiteCodeToId[$website])) { $this->addRowError(self::ERROR_INVALID_WEBSITE, $rowNum); diff --git a/app/code/core/Mage/Newsletter/Model/Template.php b/app/code/core/Mage/Newsletter/Model/Template.php index 1d286ac3e4c..44e4b64d19d 100644 --- a/app/code/core/Mage/Newsletter/Model/Template.php +++ b/app/code/core/Mage/Newsletter/Model/Template.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Template model * @@ -79,31 +82,51 @@ protected function _construct() */ public function validate() { - $validators = [ - 'template_code' => [Zend_Filter_Input::ALLOW_EMPTY => false], - 'template_type' => 'Int', - 'template_sender_email' => 'EmailAddress', - 'template_sender_name' => [Zend_Filter_Input::ALLOW_EMPTY => false], - ]; - $data = []; - foreach (array_keys($validators) as $validateField) { - $data[$validateField] = $this->getDataUsingMethod($validateField); - } - - $validateInput = new Zend_Filter_Input([], $validators, $data); - if (!$validateInput->isValid()) { - $errorMessages = []; - foreach ($validateInput->getMessages() as $messages) { - if (is_array($messages)) { - foreach ($messages as $message) { - $errorMessages[] = $message; - } - } else { - $errorMessages[] = $messages; - } + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); + + $violations[] = $validator->validate($this->getDataUsingMethod('template_code'), [ + new Assert\NotBlank([ + 'message' => 'You must give a non-empty value for field \'template_code\'', + ]), + ]); + + $message = 'You must give a non-empty value for field \'template_type\''; + $violations[] = $validator->validate($this->getDataUsingMethod('template_type'), [ + new Assert\NotBlank([ + 'message' => $message, + ]), + new Assert\Type([ + 'type' => 'int', + 'message' => $message, + ]), + ]); + + $message = '\'invalid-email\' is not a valid email address in the basic format local-part@hostname'; + $violations[] = $validator->validate($this->getDataUsingMethod('template_sender_email'), [ + new Assert\NotBlank([ + 'message' => $message, + ]), + new Assert\Email([ + 'message' => $message, + ]), + ]); + + $violations[] = $validator->validate($this->getDataUsingMethod('template_sender_name'), [ + new Assert\NotBlank([ + 'message' => 'You must give a non-empty value for field \'template_sender_name\'', + ]), + ]); + + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); } + } - Mage::throwException(implode("\n", $errorMessages)); + if (count($errors) !== 0) { + Mage::throwException(implode("\n", iterator_to_array($errors))); } } @@ -111,6 +134,7 @@ public function validate() * Processing object before save data * * @inheritDoc + * @throws Mage_Core_Exception */ protected function _beforeSave() { @@ -147,7 +171,7 @@ public function isValidForSend() /** * Getter for template type * - * @return int|string + * @return int */ public function getType() { @@ -280,7 +304,8 @@ public function getMail() * @param array $variables template variables * @param string|null $name receiver name (if subscriber model not specified) * @param Mage_Newsletter_Model_Queue|null $queue queue model, used for problems reporting. - * @return bool + * @return bool + * @throws Exception|Throwable * @deprecated since 1.4.0.1 **/ public function send($subscriber, array $variables = [], $name = null, ?Mage_Newsletter_Model_Queue $queue = null) @@ -346,7 +371,7 @@ public function send($subscriber, array $variables = [], $name = null, ?Mage_New if (!is_null($queue)) { $subscriber->received($queue); } - } catch (Exception $e) { + } catch (Exception $exception) { if ($subscriber instanceof Mage_Newsletter_Model_Subscriber) { // If letter sent for subscriber, we create a problem report entry $problem = Mage::getModel('newsletter/problem'); @@ -354,7 +379,7 @@ public function send($subscriber, array $variables = [], $name = null, ?Mage_New if (!is_null($queue)) { $problem->addQueueData($queue); } - $problem->addErrorData($e); + $problem->addErrorData($exception); $problem->save(); if (!is_null($queue)) { @@ -362,7 +387,7 @@ public function send($subscriber, array $variables = [], $name = null, ?Mage_New } } else { // Otherwise throw error to upper level - throw $e; + throw $exception; } return false; } @@ -374,6 +399,7 @@ public function send($subscriber, array $variables = [], $name = null, ?Mage_New * Prepare Process (with save) * * @return $this + * @throws Throwable * @deprecated since 1.4.0.1 */ public function preprocess() @@ -388,6 +414,7 @@ public function preprocess() * Retrieve processed template subject * * @return string + * @throws Exception */ public function getProcessedTemplateSubject(array $variables) { diff --git a/app/code/core/Mage/Newsletter/controllers/SubscriberController.php b/app/code/core/Mage/Newsletter/controllers/SubscriberController.php index a68534799d5..4e4dd6742cc 100644 --- a/app/code/core/Mage/Newsletter/controllers/SubscriberController.php +++ b/app/code/core/Mage/Newsletter/controllers/SubscriberController.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Newsletter subscribe controller * @@ -41,9 +44,10 @@ public function newAction() $session = Mage::getSingleton('core/session'); $customerSession = Mage::getSingleton('customer/session'); $email = (string) $this->getRequest()->getPost('email'); + $validator = Validation::createValidator(); try { - if (!Zend_Validate::is($email, 'EmailAddress')) { + if ($validator->validate($email, [new Assert\NotBlank(), new Assert\Email()])->count() > 0) { Mage::throwException($this->__('Please enter a valid email address.')); } diff --git a/app/code/core/Mage/Review/Model/Review.php b/app/code/core/Mage/Review/Model/Review.php index 8a2cdcad51a..075c9ee08e7 100644 --- a/app/code/core/Mage/Review/Model/Review.php +++ b/app/code/core/Mage/Review/Model/Review.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Review model * @@ -137,29 +140,37 @@ public function getReviewUrl() } /** - * @return array|bool - * @throws Zend_Validate_Exception + * @return array|true */ public function validate() { - $errors = []; + $validator = Validation::createValidator(); + $violations = []; + $errors = new ArrayObject(); - if (!Zend_Validate::is($this->getTitle(), 'NotEmpty')) { - $errors[] = Mage::helper('review')->__('Review summary can\'t be empty'); - } + $violations[] = $validator->validate($this->getTitle(), [new Assert\NotBlank([ + 'message' => Mage::helper('review')->__('Review summary can\'t be empty'), + ])]); - if (!Zend_Validate::is($this->getNickname(), 'NotEmpty')) { - $errors[] = Mage::helper('review')->__('Nickname can\'t be empty'); - } + $violations[] = $validator->validate($this->getNickname(), [new Assert\NotBlank([ + 'message' => Mage::helper('review')->__('Nickname can\'t be empty'), + ])]); - if (!Zend_Validate::is($this->getDetail(), 'NotEmpty')) { - $errors[] = Mage::helper('review')->__('Review can\'t be empty'); + $violations[] = $validator->validate($this->getDetail(), [new Assert\NotBlank([ + 'message' => Mage::helper('review')->__('Review can\'t be empty'), + ])]); + + foreach ($violations as $violation) { + foreach ($violation as $error) { + $errors->append($error->getMessage()); + } } - if (empty($errors)) { + if (count($errors) === 0) { return true; } - return $errors; + + return (array) $errors; } /** diff --git a/app/code/core/Mage/Widget/Model/Widget/Instance.php b/app/code/core/Mage/Widget/Model/Widget/Instance.php index ee861135032..f9926f94abd 100644 --- a/app/code/core/Mage/Widget/Model/Widget/Instance.php +++ b/app/code/core/Mage/Widget/Model/Widget/Instance.php @@ -170,7 +170,7 @@ protected function _beforeSave() /** * Validate widget instance data * - * @return string|bool + * @return string|true */ public function validate() { diff --git a/app/code/core/Mage/Wishlist/Model/Item.php b/app/code/core/Mage/Wishlist/Model/Item.php index efd734eda09..01961bf502f 100644 --- a/app/code/core/Mage/Wishlist/Model/Item.php +++ b/app/code/core/Mage/Wishlist/Model/Item.php @@ -231,7 +231,7 @@ protected function _afterSave() * Validate wish list item data * * @throws Mage_Core_Exception - * @return bool + * @return true */ public function validate() { diff --git a/app/code/core/Mage/Wishlist/controllers/IndexController.php b/app/code/core/Mage/Wishlist/controllers/IndexController.php index c9530cab8d0..b619cdfd479 100644 --- a/app/code/core/Mage/Wishlist/controllers/IndexController.php +++ b/app/code/core/Mage/Wishlist/controllers/IndexController.php @@ -14,6 +14,9 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validation; + /** * Wishlist front controller * @@ -656,9 +659,10 @@ public function sendAction() } elseif (count($emails) > 5) { $error = $this->__('Please enter no more than 5 email addresses.'); } else { + $validator = Validation::createValidator(); foreach ($emails as $index => $email) { $email = trim($email); - if (!Zend_Validate::is($email, 'EmailAddress')) { + if ($validator->validate($email, [new Assert\NotBlank(), new Assert\Email()])->count() > 0) { $error = $this->__('Please input a valid email address.'); break; } diff --git a/composer.json b/composer.json index b01378a3592..fa816579104 100644 --- a/composer.json +++ b/composer.json @@ -40,11 +40,13 @@ "phpseclib/mcrypt_compat": "^2.0.3", "phpseclib/phpseclib": "^3.0.14", "shardj/zf1-future": "^1.24.1", + "symfony/mime": "^6.4", "symfony/polyfill-php82": "^1.31", "symfony/polyfill-php83": "^1.31", "symfony/polyfill-php84": "^1.31", "symfony/string": "^6.4", "symfony/translation-contracts": "^3.5", + "symfony/validator": "^6.4", "tinymce/tinymce": "^7.5" }, "require-dev": { @@ -154,8 +156,9 @@ "php-cs-fixer:test": "vendor/bin/php-cs-fixer fix --dry-run --diff", "php-cs-fixer:fix": "vendor/bin/php-cs-fixer fix", "phpmd": "vendor/bin/phpmd app/code/core/Mage text .phpmd.dist.xml --color --cache --baseline-file .phpmd.dist.baseline.xml", - "phpstan": "XDEBUG_MODE=off php vendor/bin/phpstan analyze", - "phpstan:baseline": "XDEBUG_MODE=off php vendor/bin/phpstan analyze -b .phpstan.dist.baseline.neon", + "phpstan": "XDEBUG_MODE=off php vendor/bin/phpstan analyze -c .phpstan.dist.openmage.neon", + "phpstan:baseline": "XDEBUG_MODE=off php vendor/bin/phpstan analyze -c .phpstan.dist.openmage.neon -b .phpstan.dist.baseline.neon", + "phpstan:phpunit": "XDEBUG_MODE=off php vendor/bin/phpstan analyze -c .phpstan.dist.phpunit.neon", "phpunit:test": "XDEBUG_MODE=off php vendor/bin/phpunit --configuration .phpunit.dist.xml --testsuite Base,Error,Mage,Varien --no-coverage", "phpunit:coverage": "XDEBUG_MODE=coverage php vendor/bin/phpunit --configuration .phpunit.dist.xml --testsuite Base,Error,Mage,Varien --testdox", "phpunit:coverage-local": "XDEBUG_MODE=coverage php vendor/bin/phpunit --configuration .phpunit.dist.xml --testsuite Base,Error,Mage,Varien --coverage-html build/coverage", @@ -173,6 +176,7 @@ "phpmd": "Run phpmd", "phpstan": "Run phpstan", "phpstan:baseline": "Run phpstan and update baseline", + "phpstan:phpunit": "Run phpstan for PHPUnit tests", "phpunit:test": "Run PHPUnit", "phpunit:coverage": "Run PHPUnit with code coverage (requires XDEBUG enabled)", "phpunit:coverage-local": "Run PHPUnit with local HTML code coverage (requires XDEBUG enabled)", diff --git a/composer.lock b/composer.lock index 080d3be4df2..87f966b409a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eec662dd6fa517fe6e35f333e5a4a071", + "content-hash": "3f6e15b36018614e6bc8943aa6390d26", "packages": [ { "name": "colinmollenhour/cache-backend-redis", @@ -1718,6 +1718,91 @@ ], "time": "2024-12-29T13:51:37+00:00" }, + { + "name": "symfony/mime", + "version": "v6.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "fec8aa5231f3904754955fad33c2db50594d22d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/fec8aa5231f3904754955fad33c2db50594d22d1", + "reference": "fec8aa5231f3904754955fad33c2db50594d22d1", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.4|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v6.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-27T13:27:38+00:00" + }, { "name": "symfony/polyfill-ctype", "version": "v1.31.0", @@ -1875,6 +1960,89 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.31.0", @@ -2743,6 +2911,103 @@ ], "time": "2024-09-25T14:20:29+00:00" }, + { + "name": "symfony/validator", + "version": "v6.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "47610116f476595b90c368ff2a22514050712785" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/47610116f476595b90c368ff2a22514050712785", + "reference": "47610116f476595b90c368ff2a22514050712785", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php83": "^1.27", + "symfony/translation-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/annotations": "<1.13", + "doctrine/lexer": "<1.1", + "symfony/dependency-injection": "<5.4", + "symfony/expression-language": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/intl": "<5.4", + "symfony/property-info": "<5.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.13|^2", + "egulias/email-validator": "^2.1.10|^3|^4", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/", + "/Resources/bin/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to validate values", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/validator/tree/v6.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-30T18:50:04+00:00" + }, { "name": "tinymce/tinymce", "version": "7.8.0", @@ -7748,5 +8013,5 @@ "platform-overrides": { "php": "8.1" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" }