Showing ideas with status Investigating.
Show all ideas
Status:
Investigating
Submitted on
08-30-2016
12:31 PM
Submitted by
apiuser
on
08-30-2016
12:31 PM
Feature request from arunkasyakar, posted on GitHub Dec 04, 2015
i am trying to add shipment information for an order but i am getting internal error
URL(POST): http://MYHOST/rest/default/V1/shipment/
payload:
{
"entity": {
"billingAddressId": 24,
"customerId": 8,
"emailSent": 0,
"orderId": 12,
"packages": [
{
"extensionAttributes": {}
}
],
"shippingAddressId": 23,
"storeId": 1,
"items": [
{
"orderItemId": 20,
"qty": 1,
"extensionAttributes": {}
}
],
"extensionAttributes": {}
}
}
response:
{
"messages": {
"error": [
{
"code": 500,
"message": "Server internal error. See details in report api/266657385283"
}
]
}
}
api/266657385283:
s:200:"Fatal Error: 'Cannot instantiate interface Magento\Sales\Api\Data\ShipmentPackageInterface' in '/var/www/html/MYPROJECT/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php' on line 73";
... View more
Status:
Investigating
Submitted on
08-30-2016
12:31 PM
Submitted by
apiuser
on
08-30-2016
12:31 PM
Feature request from webkul, posted on GitHub Dec 14, 2015
cloudflare / CDN issue - product grid does not load - We are getting a very random issue whenever we supply the cloudlare on our server magento2 catalog grid does not load also throw an error related to backbone.js in admin product add at browser console.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:31 PM
Submitted by
apiuser
on
08-30-2016
12:31 PM
Feature request from erikhansen, posted on GitHub Jan 07, 2016
This issue covers what I consider to be two major usability issues with messages:
1. Error message hides after 5 seconds
When error messages are displayed on the frontend, they disappear after 5 seconds (this is controlled by the onHiddenChange method in app/code/Magento/Ui/view/frontend/web/js/view/messages.js ). If a user is not paying attention, if they are a slow reader, or if the error message is long, they message may disappear before they read the entire message. My recommendation would be to NOT hide the message but to leave it on the page until the user takes some other action that causes the message to be hidden.
Here is an example of an error message that will hide after 5 seconds:
@mttjohnson did some digging into what happens when there is an error with a payment method in the checkout process. It looks like the payment methods use the Magento_Ui/js/modal/alert component to display an alert-style modal that doesn't go away until the user closes it. The red error message I displayed above occurs when there is an exception thrown by Magento when progressing from Shipping > Billing, so it may not warrant an alert style popup, but it should at least persist on the page and not hide. This is what the alert-style popup looks like:
2. Error messages may display outside of current viewport
If a user is a on a small screen device, there are many situations where they will never see an error message. For example, if they're on the "Shipping" step of the checkout process and an error message is added, they may not see the error message get added to the top of the page. My suggestion would be to either smooth scroll the user up to the error message, display the error message next to the button they used to submit, or come up with a notification system that display notifications on top of all content.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:31 PM
Submitted by
apiuser
on
08-30-2016
12:31 PM
Feature request from keithbentrup, posted on GitHub Jan 19, 2016
Steps to reproduce
1) Install the reference store with a sample data
2) Configure js minification and deploy static assets
3) Visit a product page
Expected result:
Product page loads with product image and no js error in the js console
Actual result:
Product pages with no product image and a js error
Root cause:
JShrink munges lib/web/fotorama/fotorama.js. In my tests, JShrink 1.0.1 and JShrink 1.1.0 both munge the javascript when minifying.
This is a common problem with javascript minifiers. I've found yuicompressor to be much better, and when I minified with fotorama.js with yuicompressor, it worked.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from fooman, posted on GitHub Feb 14, 2016
This code
private function load()
{
if ($this->packageModuleMap === null) {
$jsonData = $this->reader->getComposerJsonFiles()->toArray();
foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $moduleDir) {
$key = $moduleDir . '/composer.json';
assumes that the registered path also holds the composer.json file which is not necessarily the case (for example https://github.com/fooman/sameorderinvoicenumber-m2/tree/v2.0.2/src). I am hoping there is a way to query composer itself for all packages of type magento2-module.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from ruby10, posted on GitHub Feb 19, 2016
Here we have two scenarios to observer
1) order created for bundle-product which has value "separately" set for "Ship Bundle Items" field in it's settings : As shown in picture
If we create shipment record for child items via api "POST /V1/shipment/" it creating shipment record but with no data under "Items Shipped" block on shipment record, as shown in screenshot
Also , we are able to create shipment for entire bundle product perfectly , which should not be the case since we have opted "seperatey" for shipping in items settings.
2) order created for bundle-product which has value "together" set for "Ship Bundle Items" field:
The behavior is same here as it happening in scenario 1. Point to be noted here is for bundle product with "together" shipping setting, we should not be able to create shipments record for child items even if it is with blank data for "Items Shipment" record on shipment record.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from wozniakm, posted on GitHub Mar 14, 2016
Steps to reproduce
Create configurable product
Call REST API to get products, for example GET /rest/V1/products?searchCriteria[page_size]=3
Expected result
Returned array should contain your added product with extension_attributes key inside
Actual result
The extension_attributes is not present
In ProductRepository there is a line $this->extensionAttributesJoinProcessor->process($collection); which calls method responsible for extension_attributes, but despite that they are not included into product. If you request product details by calling GET /rest/V1/products/:sku the extension_attributes array is present.
It really makes no sense to call API once to get products, then call API to get configurable product details and then, finally, call API to get values and labels for configurable options. Is there easier way?
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from stefandoorn, posted on GitHub Mar 16, 2016
I just stumbled into the fact that module-shipping requires zendframework/zend-http for its unit tests. So basically if I just want to do the tests of that module isolated (my module depends on that module again), I can't do that now as the requirements are not met.
So my proposal is that every module composer.json should specify the requirements needed to use that module stand-alone (the tests e.g.).
Probably has some impact, but it will improve module development imo.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from sameasterling, posted on GitHub Mar 26, 2016
if a configurable product has an only one variation, this variation should be preselected.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from gamort, posted on GitHub Apr 20, 2016
The current documentation/implementation of composer allows for a large number of attack surfaces.
A "deployed" website[ie a website either installed using composer or a website which is installed from a downloaded zip file] should not have any need for the various development requirements - such as phpunit and other dev tools. Instead of requiring installers to remember to pass --no-dev to the commands - these options can be defined in the composer.json file [ie have a composer.json.dev and a composer.json.prod file - leave composer.json as it is in the github repository, but during the build process swap for the production/safer composer file].
By the same token, using the development version of vendor libraries adds yet more insecurity. A quick search for $_GET variables shows a large number of unsafe usages in the folder lusitanian/oauth/examples - with no fault to the library author. Examples and demo code do not need to be secure - it is expected that implementors would not deploy such code.
For the oath examples, they are protected by the htaccess files from direct access - however if Magento2 can be tricked into loading one that leads to security issues. Due to the reliance on the composer autoloading mechanisms such mischief is possible in theory.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from Vinai, posted on GitHub Apr 21, 2016
Steps to reproduce
Create a class with a dependency on \Magento\Quote\Api\Data\CartInterface
Add a product to the cart
Execute the code within the same session
Expected result
The CartInterface instance represents the current quote
\Magento\Quote\Api\Data\CartInterface::getItems returns the items in the cart
Actual result
The injected CartInterface instance is empty.
To retrieve the current quote items \Magento\Checkout\Model\Session::getQuote() has to be used.
This is problematic since neither \Magento\Checkout\Model\Session nor \Magento\Quote\Model\Quote are blessed with the @api interface.
The alternative would be to use \Magento\Quote\Model\GuestCart\GuestCartRepository::get() or \Magento\Quote\Api\CartManagementInterface::getCartForCustomer , but for guests that would require having the masked cart id.
It is quite common for customizations to require access to the current cart contents. It would be nice if that could be handled with a simple dependency on CartInterface .
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from ldusan84, posted on GitHub May 02, 2016
Steps to reproduce
Install Magento from develop branch.
Create a class that extends Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction .
Use that mass action from dropdown.
Expected result
No errors.
Actual result
PHP Fatal error: Call to a member function create() on null in /var/www/html/magento2/app/code/Magento/Sales/Controller/Adminhtml/Order/AbstractMassAction.php on line 54
There is a hidden dependency in https://github.com/magento/magento2/blob/develop/app/code/Magento/Sales/Controller/Adminhtml/Order/AbstractMassAction.php#L54
It is not obvious that the child class requires collectionFactory to be injected so it's not transparent which objects are needed for this class to work.
I tried to create a PR for this, by moving the collection factory to constructor, but the problem is that for example this class:
https://github.com/magento/magento2/blob/develop/app/code/Magento/Sales/Controller/Adminhtml/Order/Pdfinvoices.php
Requires Magento\Sales\Model\ResourceModel\Order\Collection and this one:
https://github.com/magento/magento2/blob/develop/app/code/Magento/Sales/Controller/Adminhtml/Shipment/AbstractShipment/Pdfshipments.php
Requires Magento\Sales\Model\ResourceModel\Order\Shipment\CollectionFactory
These two don't have the same parent class or interface, so it seems that it's not possible to type hint.
Any thoughts?
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from SidneyBilliet, posted on GitHub May 12, 2016
Steps to reproduce
Install Magento from develop branch.
Make sure you have more than 20 orders so you have at least two pages in the order grid
go to page 2 (or 3, or 4...) and open an order by clicking 'view'
Click the "back" button on the order view page
Expected result
You should be redirected to the page 2 (or 3, or 4...) of the order grid (where you opened the order)
Actual result
Instead you are always redirected to page 1 of the order grid
... View more
Status:
Investigating
Submitted on
08-30-2016
12:30 PM
Submitted by
apiuser
on
08-30-2016
12:30 PM
Feature request from benchmarky, posted on GitHub May 14, 2016
Steps to reproduce
Create Simple Product, fill details and set price to $10.
Go to Advanced Settings > Advanced Pricing > Tier Price
Set Tier Price for customer group "NOT LOGGED IN", qty "1", price $15.
*point is to set tier pricing higher than regular price
Flush cache
Visit front end store
Expected result
See price for "NOT LOGGED IN" users as $15
Actual result
Price appears as $10 for "NOT LOGGED IN" users
--
This function is important due to the removal of the group pricing feature. For B2B stores this is a simple feature that would prevent the need for additional extensions for managing different pricing for different groups.
This would of course mean adjusting the logic of how pricing is shown in the front end, to only show that price and not do a crazy: $10, as low as $15 in the front end.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:29 PM
Submitted by
apiuser
on
08-30-2016
12:29 PM
Feature request from bgkavinga, posted on GitHub May 23, 2016
In module-catalog/Model/Layer/Filter/AbstractFilter.php::isOptionReducesResults() checks whether the resulting option count is greater than products count. There could be an option that applies to all the products. Since this logic does not check equality, the option that applies to all the products in that category will not be shown.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:29 PM
Submitted by
apiuser
on
08-30-2016
12:29 PM
Feature request from kassner, posted on GitHub May 23, 2016
Hi,
I have an email template with this:
<strong>Comments:</strong> {{var comments|nl2br}}
So, if the user adds an HTML tag, it is not escaped in the email template. The thing is that is not possible to combine escape and nl2br at the same time. Is there a way to achieve this without a plugin?
Thanks!
... View more
Status:
Investigating
Submitted on
08-30-2016
12:29 PM
Submitted by
apiuser
on
08-30-2016
12:29 PM
Feature request from leoquijano, posted on GitHub May 24, 2016
Hi,
I've been debugging some checkout issues. I noticed that several of them were fixed in Magento 2.0.7, so I went in to test our payment process using that version.
As I tested my integration with Autorize.NET DPM gateway, my checkout page froze in the "loading" stage. The order was successfully received and Authorize.NET debug log showed the information. However, something was happening after the response came back.
Sometimes I would get a window saying "Cannot place order". Sometimes it would just get stuck. However, at no point I would get more detailed information, as a developer, to what's going on.
I traced down the issue to the vendor/magento/module-authorizenet/Controller/Directpost/Payment/Place.php file (I'm using a Composer based install). The following method would be executed:
protected function placeCheckoutOrder()
{
$result = new DataObject();
$response = $this->getResponse();
try {
$this->cartManagement->placeOrder($this->_getCheckout()->getQuote()->getId());
$result->setData('success', true);
$this->eventManager->dispatch(
'checkout_directpost_placeOrder',
[
'result' => $result,
'action' => $this
]
);
} catch (\Exception $exception) {
$result->setData('error', true);
$result->setData('error_messages', __('Cannot place order.'));
}
if ($response instanceof Http) {
$response->representJson($this->jsonHelper->jsonEncode($result));
}
}
Since I got the error message 'Cannot place order' a couple of times, I entered some logging statements, and got this in my log:
2016-05-24T23:08:42+00:00 INFO (6): Error placing order: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '000000010-1' for key 'SALES_ORDER_INCREMENT_ID_STORE_ID', query was: INSERT INTO `sales_order` (`state`, `status`, `protect_code`, `shipping_description`, `is_virtual`, `store_id`, `customer_id`, `base_discount_amount`, `base_grand_total`, `base_shipping_amount`, `base_shipping_tax_amount`, `base_subtotal`, `base_tax_amount`, `base_to_global_rate`, `base_to_order_rate`, `discount_amount`, `grand_total`, `shipping_amount`, `shipping_tax_amount`, `store_to_base_rate`, `store_to_order_rate`, `subtotal`, `tax_amount`, `total_qty_ordered`, `customer_is_guest`, `customer_note_notify`, `customer_group_id`, `quote_id`, `base_shipping_discount_amount`, `base_total_due`, `shipping_discount_amount`, `subtotal_incl_tax`, `total_due`, `weight`, `increment_id`, `base_currency_code`, `customer_email`, `customer_firstname`, `customer_lastname`, `customer_middlename`, `global_currency_code`, `order_currency_code`, `remote_ip`, `shipping_method`, `store_currency_code`, `store_name`, `total_item_count`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `shipping_incl_tax`, `base_shipping_incl_tax`, `gift_message_id`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
So it is clearly an inconsistent database state. I deleted the contents from the sales_order table and the checkout now works fine.
However, it would be a good idea to provide feedback for developers when an order placement fails. Something like this:
protected function placeCheckoutOrder()
{
$result = new DataObject();
$response = $this->getResponse();
try {
$this->cartManagement->placeOrder($this->_getCheckout()->getQuote()->getId());
$result->setData('success', true);
$this->eventManager->dispatch(
'checkout_directpost_placeOrder',
[
'result' => $result,
'action' => $this
]
);
} catch (\Exception $exception) {
$this->_logger->info("Error placing order: ".$exception->getMessage());
$result->setData('error', true);
$result->setData('error_messages', __('Cannot place order.'));
}
if ($response instanceof Http) {
$response->representJson($this->jsonHelper->jsonEncode($result));
}
}
... where $this->_logger is an appropriately configured logger (via DI). This would provide something to the developer to work with, and prevent exception swallowing.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:29 PM
Submitted by
apiuser
on
08-30-2016
12:29 PM
Feature request from rasmuswikman, posted on GitHub May 26, 2016
Steps to reproduce
Edit product with custom options with more than 20 options
Expected result
Options draggable
Actual result
Can't drag options between pages
... View more
Status:
Investigating
Submitted on
08-30-2016
12:29 PM
Submitted by
apiuser
on
08-30-2016
12:29 PM
Feature request from pynej, posted on GitHub Jun 03, 2016
If you set up multiple Magneto installs and varnish and get everything working. When you clear the Page Cache on one site it clears all magneto instances cache. The command passed to varnish should include a host header to allow the vcl file to filter ban's on that header.
This adds the current domain to the purge request.
--- vendor/magento/module-cache-invalidate/Model/PurgeCache.php.old 2016-06-03 14:14:45.320427000 -0400
+++ vendor/magento/module-cache-invalidate/Model/PurgeCache.php 2016-06-03 14:32:58.908971000 -0400
@@ -7,10 +7,12 @@
use Magento\Framework\Cache\InvalidateLogger;
use Magento\Framework\App\DeploymentConfig;
+use Magento\Framework\App\RequestInterface;
class PurgeCache
{
const HEADER_X_MAGENTO_TAGS_PATTERN = 'X-Magento-Tags-Pattern';
+ const HEADER_HOST = 'host';
/**
* @var \Magento\PageCache\Model\Cache\Server
@@ -28,6 +30,11 @@
private $logger;
/**
+ * @var RequestInterface
+ */
+ private $request;
+
+ /**
* Constructor
*
* @param \Magento\PageCache\Model\Cache\Server $cacheServer
@@ -37,11 +44,13 @@
public function __construct(
\Magento\PageCache\Model\Cache\Server $cacheServer,
\Magento\CacheInvalidate\Model\SocketFactory $socketAdapterFactory,
- InvalidateLogger $logger
+ InvalidateLogger $logger,
+ RequestInterface $request
) {
$this->cacheServer = $cacheServer;
$this->socketAdapterFactory = $socketAdapterFactory;
$this->logger = $logger;
+ $this->request = $request;
}
/**
@@ -55,7 +64,7 @@
{
$socketAdapter = $this->socketAdapterFactory->create();
$servers = $this->cacheServer->getUris();
- $headers = [self::HEADER_X_MAGENTO_TAGS_PATTERN => $tagsPattern];
+ $headers = [self::HEADER_X_MAGENTO_TAGS_PATTERN => $tagsPattern, self::HEADER_HOST => $this->request->getHttpHost()];
$socketAdapter->setOptions(['timeout' => 10]);
foreach ($servers as $server) {
try {
Then the vcl files can be updated to optionally filter on the domain.
--- vendor/magento/module-page-cache/etc/varnish4.vcl.old 2016-05-16 16:18:20.000000000 -0400
+++ vendor/magento/module-page-cache/etc/varnish4.vcl 2016-06-03 15:10:56.629687000 -0400
@@ -21,6 +21,8 @@
return (synth(400, "X-Magento-Tags-Pattern header required"));
}
ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern);
+ # or only for the current domain
+ # ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern + " && obj.http.X-Req-Host == " + req.http.host);
return (synth(200, "Purged"));
}
@@ -75,6 +77,8 @@
if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}
+
+ set beresp.http.X-Req-Host = bereq.http.host;
# cache only successfully responses and 404s
if (beresp.status != 200 && beresp.status != 404) {
@@ -123,4 +127,5 @@
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
+ unset resp.http.X-Req-Host;
}
--- vendor/magento/module-page-cache/etc/varnish3.vcl.old 2016-05-16 16:18:20.000000000 -0400
+++ vendor/magento/module-page-cache/etc/varnish3.vcl 2016-06-03 15:05:46.033544000 -0400
@@ -28,6 +28,8 @@
error 400 "X-Magento-Tags-Pattern header required";
}
ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern);
+ # or only for the current domain
+ # ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern + " && obj.http.X-Req-Host == " + req.http.host);
error 200 "Purged";
}
@@ -85,6 +87,8 @@
set beresp.do_gzip = true;
}
+ set beresp.http.X-Req-Host = bereq.http.host;
+
# cache only successfully responses and 404s
if (beresp.status != 200 && beresp.status != 404) {
set beresp.ttl = 0s;
@@ -128,4 +132,5 @@
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
+ unset resp.http.X-Req-Host;
}
In short this tell magento to pass the host name onto varnish they the user can choose to use this in the varnish config. In multi-domain sites it may cause more problems that it solves, but when running multiple sites on the same server one will not clear the cache of all others.
... View more
Status:
Investigating
Submitted on
08-30-2016
12:28 PM
Submitted by
apiuser
on
08-30-2016
12:28 PM
Feature request from hostep, posted on GitHub Jun 26, 2016
Steps to reproduce
Install Magento 2.1.0 using composer but use the --no-dev flag
Look at the dev/ directory in the filesystem
Expected result
The dev/ directory should be empty or non-existing
Actual result
The dev/ directory exists and contains a bunch of development stuff
Discussion
In an effort to try to find the best options of deploying a Magento 2 installation to a production server, I keep discovering issues which aren't ideal.
As a best practise, we use composer install --no-dev --prefer-dist --optimize-autoloader on a production server when deploying. I would expect that no development dependencies gets installed because of this, but this is not true.
This isn't only about the /dev directory, but also for example about the lib/web/css/docs/ directory.
The last one for example causes the setup:static-content:deploy command to compile a less file which has absolutely no purpose of existing on a production server while it takes multiple seconds to compile this file, per locale, per theme.
In a very quick test, I discovered that when removing the above directories before executing setup:di:compile and setup:static-content:deploy makes those two run about 58 seconds faster (on my local machine) then without removing those directories.
Here is a list of files/directories which I believe shouldn't get deployed to a production server:
.htaccess.sample
.php_cs
.travis.yml
CHANGELOG.md
CONTRIBUTING.md
COPYING.txt
Gruntfile.js.sample
ISSUE_TEMPLATE.md
LICENSE.txt
LICENSE_AFL.txt
nginx.conf.sample
package.json.sample
php.ini.sample
dev/
lib/web/css/docs/
phpserver/
...
(the license files, I'm not sure about)
I think most of these files are getting into place because of the mapping in the composer.json file of the magento2-base module.
It would be great if those mappings can get split of into a mapping for development purposes and one for all environments.
My suggestion would be to add a map-dev to the extra section in the composer.json similar as the normal map section and update the magento-composer-installer project to support this and only install the map-dev files when you run composer without the --no-dev flag.
This is all theoretically, I haven't tested this properly, but let me know what you think.
I know that in your deploy scripts, you can simply delete the files you don't want after composer install --no-dev has run, but I think it makes sense to automate this, because not everyone will notice these issues.
Slightly related issues:
https://github.com/magento/magento2/issues/4245
https://github.com/magento/magento2/issues/4162
https://github.com/magento/magento2/issues/2561
... View more