Description
When trying to export a customer's data using pdf renderer I get an error
[2020-03-17 22:23:28] main.CRITICAL: Exception message: The PDF was not created successfully.
Trace: <pre>#1 Opengento\Gdpr\Service\Export\Renderer\AbstractRenderer->saveData('gdpr/e2ea3c6b50c...', array('customer' => array('email' => '[email protected]', 'firstname' => 'test', 'lastname' => 'test'), 'subscriber' => array())) called at [vendor/opengento/module-gdpr/Model/Export/ExportToFile.php:67]
#2 Opengento\Gdpr\Model\Export\ExportToFile->export(&Opengento\Gdpr\Model\ExportEntity#000000007fa568c400000000356e0a2e#) called at [vendor/opengento/module-gdpr/Model/ExportEntityManagement.php:89]
#3 Opengento\Gdpr\Model\ExportEntityManagement->export(&Opengento\Gdpr\Model\ExportEntity#000000007fa568c400000000356e0a2e#) called at [vendor/opengento/module-gdpr/Model/Export/ExportEntityData.php:68]
#4 Opengento\Gdpr\Model\Export\ExportEntityData->export(1, 'customer') called at [vendor/opengento/module-gdpr/Model/Action/Export/CreateOrExportAction.php:40]
#5 Opengento\Gdpr\Model\Action\Export\CreateOrExportAction->execute(&Opengento\Gdpr\Model\Action\Context#000000007fa568da00000000356e0a2e#) called at [vendor/opengento/module-gdpr/Model/Action/ActionComposite.php:115]
#6 Opengento\Gdpr\Model\Action\ActionComposite->process(&Opengento\Gdpr\Model\Action\Context#000000007fa568da00000000356e0a2e#) called at [vendor/opengento/module-gdpr/Model/Action/ActionComposite.php:89]
#7 Opengento\Gdpr\Model\Action\ActionComposite->execute(&Opengento\Gdpr\Model\Action\Context#000000007fa568da00000000356e0a2e#) called at [vendor/opengento/module-gdpr/Controller/Adminhtml/Privacy/MassExport.php:78]
#8 Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport->massAction(&Magento\Customer\Model\ResourceModel\Customer\Collection\Interceptor#000000007fa565f700000000356e0a2e#) called at [vendor/magento/module-customer/Controller/Adminhtml/Index/AbstractMassAction.php:65] #9 Magento\Customer\Controller\Adminhtml\Index\AbstractMassAction->execute() called at [generated/code/Opengento/Gdpr/Controller/Adminhtml/Privacy/MassExport/Interceptor.php:24]
#10 Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor->execute() called at [vendor/magento/framework/App/Action/Action.php:108]
#11 Magento\Framework\App\Action\Action->dispatch(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/module-backend/App/AbstractAction.php:231]
#12 Magento\Backend\App\AbstractAction->dispatch(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/framework/Interception/Interceptor.php:58]
#13 Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor->___callParent('dispatch', array(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#)) called at [vendor/magento/framework/Interception/Interceptor.php:138]
#14 Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor->Magento\Framework\Interception\{closure}(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/module-backend/App/Action/Plugin/Authentication.php:143] #15 Magento\Backend\App\Action\Plugin\Authentication->aroundDispatch(&Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor#000000007fa5676600000000356e0a2e#, &Closure#000000007fa5676c00000000356e0a2e#, &Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/framework/Interception/Interceptor.php:135]
#16 Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor->Magento\Framework\Interception\{closure}(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/framework/Interception/Interceptor.php:153]
#17 Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor->___callPlugins('dispatch', array(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#), NULL) called at [generated/code/Opengento/Gdpr/Controller/Adminhtml/Privacy/MassExport/Interceptor.php:39]
#18 Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor->dispatch(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/framework/App/FrontController.php:159]
#19 Magento\Framework\App\FrontController->processRequest(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#, &Opengento\Gdpr\Controller\Adminhtml\Privacy\MassExport\Interceptor#000000007fa5676600000000356e0a2e#) called at [vendor/magento/framework/App/FrontController.php:99]
#20 Magento\Framework\App\FrontController->dispatch(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/framework/Interception/Interceptor.php:58]
#21 Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', array(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#)) called at [vendor/magento/framework/Interception/Interceptor.php:138]
#22 Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/framework/Interception/Interceptor.php:153]
#23 Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', array(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#), array(array('default_store_se...', 'page_cache_from_...', 'storeCookieValid...', 'install', 'configHash'))) called at [generated/code/Magento/Framework/App/FrontController/Interceptor.php:26]
#24 Magento\Framework\App\FrontController\Interceptor->dispatch(&Magento\Framework\App\Request\Http#000000007fa563c800000000356e0a2e#) called at [vendor/magento/framework/App/Http.php:116]
#25 Magento\Framework\App\Http->launch() called at [generated/code/Magento/Framework/App/Http/Interceptor.php:24]
#26 Magento\Framework\App\Http\Interceptor->launch() called at [vendor/magento/framework/App/Bootstrap.php:261]
#27 Magento\Framework\App\Bootstrap->run(&Magento\Framework\App\Http\Interceptor#000000007fa563a700000000356e0a2e#) called at [index.php:39]
</pre> [] []
The problem with the PDF renderer is it relies on the tool wkhtmltopdf and not purely on PHP. By itself this is an issue because this limits hosting environments where magento can be installed. No sane hosting provider will allow the installation of a system package in shared hosting environments.
So definitely as a first step if this PDF library is used we need to document this in the readme file that it relies on wkhtmltopdf for PDF generation. Then the user can disable it if it's not possible for his environment.
I think we could improve the warning here. The original error message is sh: 1: wkhtmltopdf: not found
but is hidden behind the custom exception thrown.
There could be a check section about dependencies in the backend. For example it could check if the command exists and report it missing so that the user can expect the error to happen.
I finally proceeded with installing wkhtmltopdf from the debian 9 repos and ended up with another error
wkhtmltopdf 0.12.4
The switch --no-outline, is not support using unpatched qt, and will be ignored.The switch --enable-external-links, is not support using unpatched qt, and will be ignored.The switch --enable-internal-links, is not support using unpatched qt, and will be ignored.The switch --disable-smart-shrinking, is not support using unpatched qt, and will be ignored.QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-sys_m2electro'
qt.qpa.screen: QXcbConnection: Could not connect to display
Could not connect to any X display.
This happens because the user needs patched qt version of wkhtmltopdf. You won't easily find the guide to install it. Thanks to ERPNext I know this is the way to install it on ubuntu / debian
sudo apt -y install libxrender1 libxext6 xfonts-75dpi xfonts-base
https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb
sudo tar -xf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz -C /opt
sudo ln -s /opt/wkhtmltox/bin/wkhtmltopdf /usr/bin/wkhtmltopdf
sudo ln -s /opt/wkhtmltox/bin/wkhtmltoimage /usr/bin/wkhtmltoimage
I'm sure you can already see how hard it is to install the PDF capabilities for a non-trained user.
Finally after installing the patched qt version I'm receiving this error
Got error 'PHP message: PHP Fatal error: Uncaught TypeError: Return value of Opengento\\Gdpr\\Model\\Export\\ExportEntityData::export() must be of the type string, object returned in /var/www/vhosts/example.com/httpdocs/vendor/opengento/module-gdpr/Model/Export/ExportEntityData.php:68
Stack trace:
#0 /var/www/vhosts/example.com/httpdocs/vendor/opengento/module-gdpr/Model/Action/Export/CreateOrExportAction.php(40): Opengento\\Gdpr\\Model\\Export\\ExportEntityData->export(1, 'customer')
#1 /var/www/vhosts/example.com/httpdocs/vendor/opengento/module-gdpr/Model/Action/ActionComposite.php(115): Opengento\\Gdpr\\Model\\Action\\Export\\CreateOrExportAction->execute(Object(Opengento\\Gdpr\\Model\\Action\\Context))
#2 /var/www/vhosts/example.com/httpdocs/vendor/opengento/module-gdpr/Model/Action/ActionComposite.php(89): Opengento\\Gdpr\\Model\\Action\\ActionComposite->process(Object(Opengento\\Gdpr\\Model\\Action\\Context))
#3 /var/www/vhosts/example.com/httpdocs/vendor/opengento/mod...
', referer: https://example.com/admin__admin/customer/index/index/key/abc53e4ca9d7864b3eb2d47cd4101ce4bbe9d61d7b37e461b21af2a350f729f3/
[Wed Mar 18 01:04:14.913795 2020] [proxy_fcgi:error] [pid 22422:tid 139794717853440] [client 37.6.144.135:49250] AH01071: Got error 'PHP message: PHP Fatal error: Uncaught Error: Call to a member function getFilePath() on string in /var/www/vhosts/example.com/httpdocs/vendor/opengento/module-gdpr/Controller/Adminhtml/Privacy/MassExport.php:81
Stack trace:
#0 /var/www/vhosts/example.com/httpdocs/vendor/magento/module-customer/Controller/Adminhtml/Index/AbstractMassAction.php(65): Opengento\\Gdpr\\Controller\\Adminhtml\\Privacy\\MassExport->massAction(Object(Magento\\Customer\\Model\\ResourceModel\\Customer\\Collection\\Interceptor))
#1 /var/www/vhosts/example.com/httpdocs/generated/code/Opengento/Gdpr/Controller/Adminhtml/Privacy/MassExport/Interceptor.php(24): Magento\\Customer\\Controller\\Adminhtml\\Index\\AbstractMassAction->execute()
#2 /var/www/vhosts/example.com/httpdocs/vendor/magento/framework/App/Action/Action.php(108): Opengento\\Gdpr\\Controller\\Adminhtml\\Privacy\\MassExport\\Interceptor->execute()
#3 /var/www/vhosts/example.com/httpdocs/vendor/magento/module-backend/App/Abstract...
', referer: https://example.com/admin__admin/customer/index/index/key/abc53e4ca9d7864b3eb2d47cd4101ce4bbe9d61d7b37e461b21af2a350f729f3/
[Wed Mar 18 01:04:34.738615 2020] [proxy_fcgi:error] [pid 23376:tid 139794726246144] [client 37.6.144.135:49264] AH01071: Got error 'PHP message: PHP Fatal error: Uncaught Error: Call to a member function getFilePath() on string in /var/www/vhosts/example.com/httpdocs/vendor/opengento/module-gdpr/Controller/Adminhtml/Privacy/MassExport.php:81
Stack trace:
#0 /var/www/vhosts/example.com/httpdocs/vendor/magento/module-customer/Controller/Adminhtml/Index/AbstractMassAction.php(65): Opengento\\Gdpr\\Controller\\Adminhtml\\Privacy\\MassExport->massAction(Object(Magento\\Customer\\Model\\ResourceModel\\Customer\\Collection\\Interceptor))
#1 /var/www/vhosts/example.com/httpdocs/generated/code/Opengento/Gdpr/Controller/Adminhtml/Privacy/MassExport/Interceptor.php(24): Magento\\Customer\\Controller\\Adminhtml\\Index\\AbstractMassAction->execute()
#2 /var/www/vhosts/example.com/httpdocs/vendor/magento/framework/App/Action/Action.php(108): Opengento\\Gdpr\\Controller\\Adminhtml\\Privacy\\MassExport\\Interceptor->execute()
#3 /var/www/vhosts/example.com/httpdocs/vendor/magento/module-backend/App/Abstract...
', referer: https://example.com/admin__admin/customer/index/index/key/abc53e4ca9d7864b3eb2d47cd4101ce4bbe9d61d7b37e461b21af2a350f729f3/
The \Opengento\Gdpr\Model\ExportEntityManagement::export
function should return an ExportEntityInterface but the \Opengento\Gdpr\Model\Export\ExportEntityData::export
is set to return a string. It can return string or ExportEntityInterface though in the return statement. Which one is correct?
PS: I'd submit a pull request but unfortunately I don't know how this part was designed. The easiest way would be to allow string or ExportEntityInterface in \Opengento\Gdpr\Model\Export\ExportEntityData::export but it would help with consistency.
Prerequisites
PHP Version:
Magento Version:
Module Version:
Issue Details
Steps to reproduce the behavior
- Go to mass actions for customers and try to export a customer's data.
- Enable pdf renderer.
Expected behavior
I would expect the pdf file to be rendered.
Additional context