Paypal SDK Class Name Conflicts - cakephp

I want to use Paypal Adaptive Payments and Paypal Adaptive Accounts libs in my CakePHP 2.4.x application. I am loading them via composer. My composer.json file looks like this:
{
"require": {
"paypal/adaptivepayments-sdk-php":"v3.6.106",
"paypal/adaptiveaccounts-sdk-php":"v3.6.106"
},
"config": {
"vendor-dir": "Vendor"
}
}
Both libs contain Paypal/Types/Common/RequestEnvelope.php and for each lib they are different. I'm running into a conflict with this class name where the right one isn't being used. I believe the solution is to use autoload in my composer.json. I've read the documentation and don't believe I'm using it correctly. Here is what I'm attempting:
{
"require": {
"paypal/adaptivepayments-sdk-php":"v3.6.106",
"paypal/adaptiveaccounts-sdk-php":"v3.6.106"
},
"config": {
"vendor-dir": "Vendor"
},
"autoload": {
"psr-4": {
"AdaptivePaymentsLib\\": "Vendor/paypal/adaptivepayments-sdk-php/lib",
"AdaptiveAccountsLib\\": "Vendor/paypal/adaptiveaccounts-sdk-php/lib"
}
}
}
And in my controller I'm attempting to call RequestEnvelope like this:
$requestEnvelope = new AdaptivePaymentsLib\PayPal\Types\Common\RequestEnvelope("en_US");
It is not being found. Active Accounts was only recently added to the project. Previously getting the request envelope worked fine with $requestEnvelope = new PayPal\Types\Common\RequestEnvelope("en_US"); so it was only with the addition of the accounts which presented the conflict and caused the breakage.

You should not define autoloading for your dependencies - that is the task for them to solve.
If you look at the composer.json file for paypal/adaptivepayments-sdk-php, you see:
"autoload": {
"psr-0": {
"PayPal\\Service": "lib/",
"PayPal\\Types": "lib/"
}
}
If you look at the same file in paypal/adaptiveaccounts-sdk-php, you see:
"autoload": {
"psr-0": {
"PayPal\\Service": "lib/",
"PayPal\\Types": "lib/"
}
}
After installing, Composer creates a file vendor/composer/autoload_namespaces.php with this content:
return array(
'PayPal\\Types' => array($vendorDir . '/paypal/adaptivepayments-sdk-php/lib', $vendorDir . '/paypal/adaptiveaccounts-sdk-php/lib'),
'PayPal\\Service' => array($vendorDir . '/paypal/adaptivepayments-sdk-php/lib', $vendorDir . '/paypal/adaptiveaccounts-sdk-php/lib'),
'PayPal' => array($vendorDir . '/paypal/sdk-core-php/lib'),
);
So both libraries are included here, and I have no doubt the autoloading will work.
You cannot really do something about the duplicate classes with different content. Did you open an issue on Github? Without making the developer team aware of this problem, it will never get solved.
As a hack, you could define a post-install and post-update script that deletes one of these files. See the composer documentation for more details. Composer accepts either any shell command, or a static call to a PHP class. I'd go with the shell command here.

Related

Is it good to use package.json file in react component file?

I have to use version mentioned in package.json file in front-end(react js) file.
{
"name": "asdfg",
"version": "3.5.2", // want to use this
"description": "description",
"scripts": {}
//etc etc etc
......
}
Send package.json [version] to Angularjs Front end for display purposes
I'd gone through above post and found two ways for the same. but none of them I was asked to implement.
#1. During build process
#2. By creating endpoint
So I want to know the approach below is valid/good or not ?
react-front-end-file.js
import packageJson from '../package.json'; // imported
...
...
// Usage which gives me version - 3.5.2
<div className='app-version'>{packageJson.version}</div>
Let me know if this approach is fine.
The below 2 approaches seems to have either dependency or add an extra implentation which might not be needed
During build process - ( has dependency on module bundler like webpack etc.)
By creating endpoint - ( needs an extra code at server just to get version )
Instead, As package.json is a file which takes json object in it so you can use it to import json and use its any keys mentioned in that file ( version in your case but only constraint here is, you should have access to package.json file after application deployment, so dont forget to move file in deployment environment )
So your approach seems to be fine.
I would do something like this:
In your module bundler, require your package json file and define a global variable and use it wherever you want
e.g. I do something like this in webpack:
const packageJson = require('./package.json')
const plugins = [
new webpack.DefinePlugin(
{
'__APPVERSION__': JSON.stringify(packageJson.version)
}
)
]
React Component:
<div className='app-version'>{__APPVERSION__}</div>

How to avoid "save as" prompt when remotely downloading file via SauceLabs

A protractor spec running from a Jenkins job, that connects to SauceLabs. It clicks a button to download a PDF, and checks that the file successfully downloaded. I am unable to get the chrome browser to NOT open a "Save As" prompt using an absolute path. I AM able to avoid the "Save As" prompt if I use '~/Downloads' as filename, but then my browser.wait that waits for the file to exist hangs forever.
// spec.js
import fs from 'fs'
import path from 'path'
fs.mkdirSync('./downloads')
describe('Clicking DOWNLOAD button', () => {
it('should download a proposal', () => {
const filename = path.resolve(__dirname, './downloads/proposal.pdf')
if (fs.existsSync(filename)) {
fs.unlinkSync(filename)
}
page.downloadProposalBtn.click()
browser.wait(() => fs.existsSync(filename), 180000)
.then(() => {
expect(fs.existsSync(filename)).toBe(true)
})
}, 180000)
})
Below is the relevant portion of my conf file. I would expect the prompt_for_download setting to make the prompt not show, but it does..
// conf.js
capabilities: {
platform: 'macOS 10.12',
browserName: 'chrome',
version: '59.0',
screenResolution: '1400x1050',
chromeOptions: {
args: ['--no-sandbox', '--test-type=browser', 'disable-infobars=true'],
prefs: {
download: {
prompt_for_download: false,
directory_upgrade: true,
default_directory: path.resolve(__dirname, './downloads'),
},
credentials_enable_service: false,
},
},
},
Am I missing something? I feel like I might be misunderstanding where Saucelabs is running these tests from, but it would seem that given I fs.mkdir the ./downloads folder, then when I path.resolve it, that should work.
Unsure if this constitutes an "answer" but this is how I'm proceeding. After a lot of research I think that testing if a file downloaded on a remote VM (like SauceLabs) isn't possible. What I am doing instead is breaking the test into two parts:
Test the download button: click the button and assert that no error occurred
Make GET request to the underlying endpoint api/download that the button is using, write the response to a folder, and from there assert (using nodejs) that the file exists in my Jenkins project's workspace. This feels hacky, but given SauceLabs doesn't seem to give much access to the VM that the webdriver is running on, I don't see another way.
You will get the prompt, even though the option is set to "false" if the default download directory doesn't exist. "./downloads" is OSX syntax, which the chrome driver probably doesn't understand.
Try this instead:
default_directory: __dirname + '/downloads'

sw-precache with angularJs application not caching

I am newbie to service worker concept so forgive me if I am overlooking something from documentation. I have an angular application already running in production and I am trying to introduce service worker using sw-precache.
To start with I am trying to precache all images/fonts and couple of js files and see if it works, so my precache config is like this -
{
"cacheId": "static-cache",
"importScripts": [
"sw-toolbox.js"
],
"stripPrefix": "dist/",
"verbose": true,
"staticFileGlobs": [
"dist/img/**.*",
"dist/javascripts/require.js",
"dist/stylesheets/**.*",
"dist/webfonts/**.{ttf, eot, woff}",
"sw-toolbox.js",
"service-worker.js"
]
}
Now I can see service worker registered and installed properly and cache storage shows all the urls with _sw-precache hashes.
But when I load the application and see in network tab all static content are still served from memory/disk, not from service worker and I am unable to debug why is it so. Am I missing something here -
UPDATE:
More information: I had wrong configurations since I have dynamic url and server side rendered html. Server side it's test.jsp which is giving me initial shell.
For now I have removed all other static files from cache and kept only show.css
So update config now is -
{
"importScripts": [
"sw-toolbox.js"
],
"stripPrefix": "dist/",
"verbose": true,
"staticFileGlobs": [
"dist/stylesheets/show.css"
],
"dynamicUrlToDependencies": {
"/developers": ["dist/stylesheets/show.css"]
},
"navigateFallback": "/developers"
}
Web root folder is named differently and it is -
- dashboard
-- img
-- javascripts
-- service-worker.js
-- sw-toolbox.js
- test.jsp
And I see /developers url as an entry in storage cache, but still it's not served from service worker for next refresh. I have tried all my energy to fix this, but I desperately need some clue here, what's missing in here. TIA.
Let me know if need more info.
It seems that whitespaces in your file extension list are not allowed. Your definition for webfonts should be:
"dist/webfonts/**.{ttf,eot,woff}",
I cloned the sw-precache repo and added a unit test where I compared two generated files with two diffrent staticFileGlobs, one with whitespace and one without.
it('should handle multiple file extensions', function(done) {
var config = {
logger: NOOP,
staticFileGlobs: [
'test/data/one/*.{txt,rmd}'
],
stripPrefix: 'test'
};
var configPrime = {
logger: NOOP,
staticFileGlobs: [
'test/data/one/*.{txt, rmd}'
],
};
generate(config, function(error, responseString) {
assert.ifError(error);
generate(configPrime, function(error, responseStringPrime) {
assert.ifError(error);
console.log('responseStringPrime',responseString);
assert.strictEqual(responseString, responseStringPrime);
done();
});
});
});
and it failed. The second config didn't include the .rmd file:
-var precacheConfig = [["/data/one/a.rmd","0cc175b9c0f1b6a831c399e269772661"],["/data/one/a.txt","933222b19ff3e7ea5f65517ea1f7d57e"],["/data/one/c.txt","fa1f726044eed39debea9998ab700388"]];
versus
+var precacheConfig = [["test/data/one/a.txt","933222b19ff3e7ea5f65517ea1f7d57e"],["test/data/one/c.txt","fa1f726044eed39debea9998ab700388"]];

CakePHP: loads plugin for test

I have a plugin (FirstPlugin).
The plugin loads a second plugin (SecondPlugin) from its bootstrap and they work both fine.
Now I'm writing tests for FirstPlugin and I need to load SecondPlugin into tests.
So in the bootstrap for test (FirstPlugin/tests/bootstrap.php) I just require the main bootstrap (FirstPlugin/config/bootstrap.php):
require ROOT . 'config' . DS . 'bootstrap.php';
I do this because I also need other bootstrap code (constant, cache settings, etc.).
This doesn't work and I can't understand which is the matter.
Note I have already modified the composer.json for FirstPlugin:
"autoload": {
"psr-4": {
"FirstPlugin\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"FirstPlugin\\Test\\": "tests",
"SecondPlugin\\": "vendor/second-plugin-path/src"
}
},
and the SecondPlugin is installed via composer and located into vendor/.
EDIT
The exception is thrown here:
http://api.cakephp.org/3.2/source-class-Cake.Core.Plugin.html#149
This means $config['path'] is empty.
The problem I think is this:
http://api.cakephp.org/3.2/source-class-Cake.Core.Plugin.html#134
Maybe in the bootstrap of test I must set manually the configuration value?
Solved.
Missing file vendor/cakephp-plugins.php.
I noticed that this file is not created for the plugin, but only for the app. Strange.

How to install a plugin manually in CakePHP 3?

I am unable to use Composer and thus have to install CakePDF plugin manually, but following examples from official CakePHP documentation does not seem to work.
So here is installation flow that I have followed:
1.) Copied the plugin to app/plugins/CakePdf
2.) Updated the app's composer.json file, like following:
"autoload": {
"psr-4": {
"CakePdf\\": "./plugins/CakePdf/src",
"CakePdf\\Test\\": "./plugins/CakePdf/tests"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests",
"Cake\\Test\\": "./vendor/cakephp/cakephp/tests"
"CakePdf\\": "./plugins/CakePdf/src",
"CakePdf\\Test\\": "./plugins/CakePdf/tests"
}
}
3.) Loaded the plugin in bootstrap.php:
Plugin::load('CakePdf', ['bootstrap' => true, 'routes' => true, 'autoload' => true]);
4.) Added router extensions:
Router::extensions(['pdf']);
5.) Tried a very simple sample from plugin's doc:
$cakePdf = new CakePdf(array(
'engine' => 'CakePdf.DomPdf',
'pageSize' => 'A4',
'orientation' => 'portrait'
));
$html = '<html><head><body><p>Pdftest</p></body></head></html>';
$rawPdf = $CakePdf->output($html);
However the code breaks at the first line and the following error message is provided:
Class 'App\Controller\CakePdf' not found
I would really appreciate any help or guidance for how a plugin should be installed manually.
If there is any other information that I need to provide, just ask.
You are getting this error because inside vendor/composer/ you can see some autoload_*.php files. These files hold the paths to load your classes. I think no one can safely tell you what to update and where in these files.
So you have two solutions:
1 - Copy composer.json on a local machine and run composer update. Then move the files created inside your app. I would suggest to take a backup before. Most probably the things that you will have to move are:
vendor/
composer.json
composer.lock
2 - Start updating the files inside vendor/composer/autoload_*.php with the paths from the plugin. Most probably you will only need to update the following two files:
vendor/cakephp-plugins.php and vendor/composer/autoload_psr4.php. Personally I wouldn't choose the second solution I am just adding it as an alternative just in case.

Resources