I'm working on a Drupal module that imports a Xlsx file and inserts the rows to database. Everything works fine, except PhpSpreadsheet throws the error "PHP message: Uncaught PHP Exception InvalidArgumentException: "File "" does not exist." at File.php line 137" when my uploaded file is in public. This error doesn't happen when the file is in base_path(). Line 137 throws an exception saying it's not a file, but \dpm(is_file($uri)) returns TRUE. Why is this happening? Below is my code:
public function submitForm(array &$form, FormStateInterface $form_state) {
$connection = \Drupal::database();
$fid = $form_state->getValue("xlsx_upload");
$input = File::load(reset($fid));
$input->setPermanent();
$uri = \Drupal::service('file_system')->realpath($input->getFileUri());
//$uri = '/home/joe/file.xslx'; <--- this works perfectly.
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile($uri);
$spreadsheet = $reader->load($filename);
$dataArray = $spreadsheet->getActiveSheet()->toArray();
$connection->truncate("mitacan")->execute();
$connection->query("SET NAMES utf8");
foreach ($dataArray as $dataItem) {
$connection->insert('mitacan')
->fields([
'stokkodu' => $dataItem[0],
'logo' => $dataItem[1],
'resim1' => $dataItem[2],
'grupkodu' => $dataItem[3],
'grupadi' => $dataItem[4],
'grupindex' => $dataItem[5],
'paketadedi' => $dataItem[6],
])
->execute();
}
drupal_set_message('Excel verisi veritabanına eklendi.');
}
$spreadsheet = $reader->load($filename);
$filename is undefined. Use $uri instead.
Related
I have a class in which default validation works just fine, but i have additional validation needs. All of the code is working fine including the default validation rules and messages defined in rules and messages function. for the sake of simplicity i'm providing the relevant code only.
The Problem:
In the store method i have a custom validator which should validate the uniquness of custom permission name. The validation rules returns this message "The given data was invalid."
I have tried different scenarios, for example: using different supposed name i.e. "permission_name", I have also tried rules in string instead of array.
$rules = ['permission_name' => 'unique:permissions,name'];
This does'nt work. Can anyone please point me in the right direct what is wrong here. Any help is appreciated in advance.
class CreatePermissionComponent extends Component
{
public $resource_name, $permission_type;
protected $validationAttributes = [
'resource_name' => 'resource name',
'permission_type' => 'permission type',
];
public function store()
{
$this->validate($this->rules(), $this->messages());
DB::beginTransaction();
try
{
// The problem
$input = ['name' => $this->resource_name . '.' . $this->permission_type];
$rules = ['name' => Rule::unique('permissions', 'name')];
$messages = ['name.unique' => 'The permission name ' . $this->resource_name . '.' . $this->permission_type . 'already exists.'];
$validatedData = Validator::make($input, $rules, $messages)->validate();
DB::commit();
ToasterHelperLivewire::toasterSuccess($this, $this->notifyMessage . ' Created Successfully.');
}
catch (\Exception $exception)
{
DB::rollback();
ToasterHelperLivewire::toasterErrorShort($this, $exception->getMessage());
}
}
public function updated($key, $value)
{
$this->validateOnly($key, $this->rules(), $this->messages());
}
protected function rules()
{
$rules = [
'resource_name' => ['required', 'alpha', 'min:3', 'max:50'],
];
if($this->permission_mode == 'single')
{
$rules['permission_type'] = ['required'];
}
else
{
$rules['permission_resource'] = ['min:1', 'array'];
}
return $rules;
}
protected function messages()
{
return [
'resource_name.alpha' => ':attribute may only contain alphabet and must be in this format. ex: users',
'permission_resource.min' => 'Please select at-least on checkbox from :attribute.',
];
}
}
I want to register an AWS Cognito Identity using getOpenIdTokenForDeveloperIdentity.
Below are my codes written in CodeIgniter framework:
Awscognitoauth.php
<?php
// <MYPROJECT>/application/controllers/Awscognitoauth.php
defined('BASEPATH') or exit('No direct script access allowed');
class Awscognitoauth extends CI_Controller {
function getOpenId($userId) {
$this->load->library('awsauth');
return $this->awsauth->identity($userId);
}
}
Awsauth.php
<?php
// <MY PROJECT>/application/libraries/Awsauth.php
defined('BASEPATH') or exit('No direct script access allowed');
require_once APPPATH . "third_party/aws/aws-autoloader.php";
use Aws\CognitoIdentity\CognitoIdentityClient;
use Aws\Sts\StsClient;
class Awsauth {
public function identity($userId) {
$region = '<my region>';
$key = '<my key>';
$secret = '<my secret>';
$version = 'latest';
$client = CognitoIdentityClient::factory(array('region' => $region, 'key' => $key, 'secret' => $secret, 'version' => $version));
$poolId = '<my pool Id>'; // formatted: "<region>:<UUID>"
$domain = '<my reversed company domain>'; // com.<company...>...
return $client->GetOpenIdTokenForDeveloperIdentity(array('IdentityPoolId' => $poolId, 'Logins' => array($domain => $userId))); // https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html
}
}
In safari, I call the controller Awscognitoauth and get the following error:
I double-checked my user's role here:
It is AdministratorAccess
Access key does match with the key in my code
What could cause this 404 Not Found response? I thought that my user has AdministratorAccess and I can access any resource. Do I miss something?
oh shoot!
I just found out that the $key and $secret must be wrapped in credentials.
So, the final code for Awsauth.php is:
<?php
// <MY PROJECT>/iot.kooltechs.com/application/libraries
defined('BASEPATH') or exit('No direct script access allowed');
require_once APPPATH . "third_party/aws/aws-autoloader.php";
use Aws\CognitoIdentity\CognitoIdentityClient;
use Aws\Sts\StsClient;
class Awsauth {
public function identity($userId) {
$region = '<my region>';
$key = '<my key>';
$secret = '<my secret>';
$version = 'latest';
$config = [
'version' => $version,
'region' => $region,
'credentials' => [
'key' => $key,
'secret' => $secret
]
];
$client = CognitoIdentityClient::factory($config);
$poolId = '<my pool Id>'; // formatted: "<region>:<UUID>"
$domain = '<my reversed company domain>'; // com.<company...>...
return $client->GetOpenIdTokenForDeveloperIdentity(array('IdentityPoolId' => $poolId, 'Logins' => array($domain => $userId)));
}
}
Regards,
I am trying without success to use the readAsDataURL function of the Cordova File plugin to get a base64 version of a video file. My code looks like this:
recordVideo()
{
return new Promise(resolve =>
{
let options: CaptureVideoOptions = { limit: 1, duration: 2 };
MediaCapture.captureVideo(options)
.then(
(data: MediaFile[]) => {
console.log('Media: recordVideo: cordova.file.dataDirectory = ' + cordova.file.dataDirectory + ', path = ' + data[0].fullPath.substring(1));
// Turn the video file into base64
let base64File = File.readAsDataURL(cordova.file.dataDirectory, data[0].fullPath.substring(1));
console.log('Media: recordVideo: got video with data = ' + JSON.stringify(data));
console.log('Media: recordVideo: base64File = ' + JSON.stringify(base64File));
resolve(data);
},
(err: CaptureError) => console.error('ERROR - Media: recordVideo: captureVideo error = ' + err)
);
});
}
The output from the first console.log shows the values of the parameters passed to the readAsDataURL:
Media: recordVideo: cordova.file.dataDirectory = file:///var/mobile/Containers/Data/Application/764345DC-A77D-43C2-9DF7-CDBE6A0DC372/Library/NoCloud/, path = private/var/mobile/Containers/Data/Application/764345DC-A77D-43C2-9DF7-CDBE6A0DC372/tmp/50713961066__4FD8AF8D-BD36-43A4-99CC-F328ADFD7E38.MOV
The second console.log shows the data returned by the MediaCapture plugin:
Media: recordVideo: got video with data = [{"name":"50713961066__4FD8AF8D-BD36-43A4-99CC-F328ADFD7E38.MOV","localURL":"cdvfile://localhost/temporary/50713961066__4FD8AF8D-BD36-43A4-99CC-F328ADFD7E38.MOV","type":"video/quicktime","lastModified":null,"lastModifiedDate":1485446813000,"size":195589,"start":0,"end":0,"fullPath":"/private/var/mobile/Containers/Data/Application/764345DC-A77D-43C2-9DF7-CDBE6A0DC372/tmp/50713961066__4FD8AF8D-BD36-43A4-99CC-F328ADFD7E38.MOV"}]
The last console.log shows the value returned by the readAsDataURL:
Media: recordVideo: base64File = {"__zone_symbol__state":null,"__zone_symbol__value":[]}
There is next to no documentation on using this (that I can find).
Function readAsDataURL gets path and filename as parameters and returns a promise. The usage is
File.readAsDataURL("path_to_the_FileName", "Filename").then(result => {
this.base64File = result;
});
As per the console log, the filename and full path to the filename are obtained from data (promise returned from MediaCapture.captureVideo).
So you can use it as below
var path = "file://"+data[0].fullPath.substring(7,data[0].fullPath.lastIndexOf("/"));
File.readAsDataURL(path, data[0].name).then(result => {
this.base64File = result;
}
If issue is this that File.readAsDataURL is not returning response nor catching error then move the cordova.js after vendor.js script (in the index.html). I was facing this issue in my ionic 3 app. I solved this from this link here.
I am trying to figure out how to access an error from a list of errors (a constant list). By access I mean that I have a new() method which outputs/creates an error that is posted. My new method does not match up properly with the way my list 'code' at the minute, so I am asking what changes I would have to make so that it will be able to retrieve an error (hash) from the list like this:
ASC::Builder:Error->new(code => UNABLE_TO_PING_SWITCH_ERROR, switch_ip => $switch_ip, timeout => $timeout); (if this is possible, I have been told it may not be, without taking code as an argument and then deleting it)
Here are my files below:
Error.pm
package ASC::Builder::Error;
use strict;
use warnings;
use ASC::Builder::Error::Type 'code';
use parent 'Exporter';
our #EXPORT_OK = qw/new/;
sub new {
my ($class, %args) = #_;
my #args = keys %args;
# Takes code in as an argument and then removes it so the error hash it self can be assigned to it
my $self = delete $args{code};
if (is_error($self)) {
return $self;
}
# 1st argument will be error hash. Any other arguments will be context params & inserted into
# context field of the error hash
if (ref $self eq 'HASH' && (#args > 1)) {
foreach my $key (#{ $self->{context} } ) {
# And take the ones we need
$self->{args}->{$key} = $args{$key};
}
my #template_args = map { $self->{args}->{$_} } #{ $self->{context} };
# Map/Insert arguments into context hash and insert into string template
$self->{message} = sprintf ($self->{template}, #template_args);
return bless $self, $class;
}
# Supporting the old error messaage (string & parameters)
else {
return bless { message => $args[0]}, $class;
}
}
# Accessor for category
sub category {
return shift->{category};
}
# Accessor for message
sub template {
return shift->{template};
}
# Accessor for context
sub context {
return shift->{context};
}
# Accessor for template option
sub tt {
return shift->{tt}{template};
}
# Accessor for fatal
sub is_fatal {
return shift->{fatal};
}
# Setter for is_fatal
sub set_is_fatal {
my ($self, $fatal) = #_;
$self->{fatal} = $fatal;
}
# Accessor for wiki_page
sub wiki_page {
return shift->{wiki_page};
}
# Accessor for args. args are a hash ref of context parameters that are
# passed in as a list at construction
sub args {
return shift->{args};
}
# Accessor for error message which is processed inside the new() method.
# Will return error message with context parameters inserted.
sub message {
return shift->{message};
}
# Stringifies the error to a log message (for SB dashboard), including the
# category, message, and wiki_page.
sub stringify {
my ($self) = #_;
return sprintf ("%s: %s\nMore info: %s",$self->{category}, $self->{message}, $self->{wiki_page});
}
# Accessor for old error message type
sub details {
my $self = shift;
return $self->{details} || $self->{message};
}
sub code {
return shift->{code};
}
# Used to deserializ from build json.
sub recreate_from_hash {
my($class, $hash) = #_;
return bless $hash, $class;
}
# Use to check if something is out error.
sub is_error {
if (scalar(#_) > 1) { # Called as $class->is_error
shift; # Get rid of class
}
return UNIVERSAL::isa(shift, 'ASC::Builder::Error');
}
1;
Type.pm (This is the list I am exporting)
package ASC::Builder::Error::Type;
use strict;
use warnings;
use parent 'Exporter';
# Export the list of errors
our #EXPORT_OK = ('code');
# List of error messages
use constant code => {
UNABLE_TO_PING_SWITCH_ERROR => {
category => 'Connection Error',
template => "Could not ping switch %s in %s seconds.",
context => [ qw(switch_ip timeout) ],
tt => {template => 'disabled'},
fatal => 1,
wiki_page => 'http://w.error-fix.com/index.php/Builder/ErrorCodes/UNABLE_TO_PING_SWITCH_ERROR',
},
# Add errors to this library
};
1;
N.B.: Can include the unit test for this design if needed.
Don't reuse the symbol code, it's confusing the issue.
You can leave your Type.pm file as is. It defines the constant code to be a reference to a hash that has one key/value pair. The key of that hash is the name of the error you eventually want to access.
In your Error.pm module, you are importing the constant code. There is no reason to be passing that in to a constructor. You can just go ahead and use it.
Change the call to your constructor to:
ASC::Builder:Error->new(error_name => 'UNABLE_TO_PING_SWITCH_ERROR', switch_ip => $switch_ip, timeout => $timeout);
Then within your constructor, you can do:
sub new {
my ($class, %args) = #_;
my $error_name = $args{error_name};
my $error_hash = code->{$error_name};
At this point, $error_hash will be a reference to the inner hash you created in Type.pm:
{
category => 'Connection Error',
template => "Could not ping switch %s in %s seconds.",
context => [ qw(switch_ip timeout) ],
tt => {template => 'disabled'},
fatal => 1,
wiki_page => 'http://w.error-fix.com/index.php/Builder/ErrorCodes/UNABLE_TO_PING_SWITCH_ERROR',
}
and you can use it accordingly. I hope that helps get you in the right direction.
I am using Cakephp 3.0.3 and I have following method in my User Entity,
public function sendRecovery()
{
$email = new Email('default');
$email->viewVars([
'userId' => $this->id,
'token' => $this->token
]);
$email->template('GintonicCMS.forgot_password')
->emailFormat('html')
->to($this->email)
->from([Configure::read('admin_mail') => Configure::read('site_name')])
->subject('Forgot Password');
return $email->send();
}
i am writing testCase for it.
here is my testCase Method.
public function testSendRecovery()
{
$entity = new User([
'id' => 1,
'email' => 'hitesh#securemetasys.com',
'token' => 'jhfkjd456d4sgdsg'
]);
$email = $this->getMock('Cake\Network\Email\Email', ['sendRecovery']);
$email->expects($this->once())
->method('sendRecovery')
->with($this->equalTo('hitesh#securemetasys.com'));
$entity->sendRecovery();
}
when i run phpunit then i got following error,
There was 1 error:
1) GintonicCMS\Test\TestCase\Model\Entity\UserTest::testSendRecovery
InvalidArgumentException: Unknown email configuration "default".
E:\xampp\htdocs\Cake3\Proball-Market\plugins\GintonicCMS\vendor\cakephp\cakephp\src\Network\Email\Email.php:1382
E:\xampp\htdocs\Cake3\Proball-Market\plugins\GintonicCMS\vendor\cakephp\cakephp\src\Network\Email\Email.php:1269
E:\xampp\htdocs\Cake3\Proball-Market\plugins\GintonicCMS\vendor\cakephp\cakephp\src\Network\Email\Email.php:383
E:\xampp\htdocs\Cake3\Proball-Market\plugins\GintonicCMS\src\Model\Entity\User.php:90
E:\xampp\htdocs\Cake3\Proball-Market\plugins\GintonicCMS\tests\TestCase\Model\Entity\UserTest.php:73
can any one help me Please?