laravel maatwebsite/excel formula error unexpected "," - php

I am fetching results from database and then creating excel sheet from it.
This stores the file in storage path.
public function downloadResults(array $filterArr) {
unset($queryArr);
$start = 0;
$limit = 10000;
$response = $this->getFilterResults($filterArr, true, $start, $limit);
$resultHits = $response['resultHits'];
# if results are empty, throw an exception
if($resultHits->isEmpty())
throw new \Exception("No results found for given filter.", 1);
# otherwise continue with the download process...
$exportArr = [];
foreach($resultHits as $key=>$value) {
$list = (array) $value;
array_push($exportArr, $list);
}
$type = 'xls';
$export = Excel::create('result_set_download_'.time(), function($excel) use ($exportArr) {
$excel->sheet('mysheet', function($sheet) use ($exportArr) {
$sheet->fromArray($exportArr);
});
})->store($type, storage_path('app/public/exports'), true);
return $export;
}
If export and store is successful, then stored filename is sent back to browser, else error message is sent.
try {
$exportArr = $this->product->downloadResults($filterArr);
$status = true;
$jsonArr['filename'] = $exportArr['file'];
} catch (\Exception $e) {
$status = false;
$jsonArr['message'] = $e->getMessage();
} finally {
$jsonArr['success'] = $status;
echo json_encode($jsonArr);
}
This is working fine until now, but in case of few exports I get this error:
mysheet!Z2898 -> Formula Error: Unexpected ,
There's not any calculation done while exporting.
I also found a similar post here
Laravel Excel Formula Error: Unexpected operator '='
And this is the answer to that post:
// Enable calculation
$reader->calculate();
// Disable calculation
$reader->calculate(false);
But I am confused as to where to put this.

If you want to enable any formula, first export your laravel-excel config
php artisan vendor:publish
Search Maatwebsite then publish it. In my case is 12. Type 12 then Enter.
That will copy a config file to your config folder.
Then from config/excel.php change this line:
excel.php
'pre_calculate_formulas' => true, // default is false

Related

how to copy/upload a locally created file to azure file storage using PHP

I'm trying to follow this link: https://learn.microsoft.com/en-us/rest/api/storageservices/copy-file
with examples from this repo: https://github.com/Azure/azure-storage-php/blob/master/samples/FileSamples.php#L235
The file is indeed copied to the azure server but the content aren't readable, to say the least, it takes a size but it's empty. This is only a text file as well, and what I plan to achieve after fixing this is to copy excel files generated via PHP to an azure file storage server.
Also, we are using file.core not blob.core
<?php
require_once "vendor/autoload.php";
use MicrosoftAzure\Storage\File\FileRestProxy;
use MicrosoftAzure\Storage\Common\Models\Range;
$accountName = "test";
$accountKey = "test";
$shareName = 'test';
$connectionString = "DefaultEndpointsProtocol=https;AccountName=$accountName;AccountKey=$accountKey";
$fileClient = FileRestProxy::createFileService($connectionString);
$dstfileName = 'demo-4.txt';
$srcfileName = 'demo-4.txt';
$sourcePath = sprintf(
'%s%s/%s',
(string)$fileClient->getPsrPrimaryUri(),
$shareName,
$srcfileName
);
try {
// Create destination file.
$fileClient->createFile($shareName, $dstfileName, 1024);
// Copy file.
return $fileClient->copyFile($shareName, $dstfileName, $sourcePath);
} catch (ServiceException $e) {
$code = $e->getCode();
$error_message = $e->getMessage();
echo $code . ": " . $error_message . PHP_EOL;
}
Update using file_get_contents
$srcfileName = 'demo-4.txt';
$content = file_get_contents('demo-4.txt');
$range = new Range(0, filesize('demo-4.txt') - 1);
$sourcePath = sprintf(
'%s%s/%s',
(string)$fileClient->getPsrPrimaryUri(),
$shareName,
$srcfileName
);
try {
// Create source file.
$fileClient->createFile($shareName, $srcfileName, 1024);
$fileClient->putFileRange($shareName, $srcfileName, $content, $range);
} catch (ServiceException $e) {
$code = $e->getCode();
$error_message = $e->getMessage();
echo $code . ": " . $error_message . PHP_EOL;
}
This is able to create the file with the content from the source file, but the problem is that the range is incorrect since I don't know how to correctly get that value.
The created file is presented by the image attached, it has multiple nulls in it because I'm guessing my range exceeds the actual length of the source file contents.
createFile method simply creates an empty file of size specified in the method call. It essentially maps to Create File REST API operation.
You should use createFileFromContent convenience method to create a file with content. It basically first creates an empty file and then writes the contents to that file.
Other option would be to call putFileRange method to write the contents to the file after you have created it using createFile method.

How to check if an uploaded file is a SQLite format file in PHP?

What I want to do is a small web page that a user can upload a SQLite file, but I want to avoid those uploads that aren't SQLite format, so I try to verify it before I execute "move_uploaded_file". Above there's an example of what I've tried to do, but it doesn't work.
function isFileOkay($filedir) {
try
{
$db = new PDO("sqlite:".$filedir);
$sql = "PRAGMA schema_version;";
$ret = $db->query($sql);
if(!$ret)
{
$db = NULL;
return -1;
}
$row = $ret->fetchAll(PDO::FETCH_BOTH);
$value = (int) $row[0]['schema_version'];
$db = NULL;
return $value;
}
catch (PDOException $exception) {
echo $exception->getMessage();
return -1;
}
}
...
$test = isFileOkay($_FILES['upload_file']['tmp_name']);
...
The $test variable should be "-1" if the file isn't a SQLite file, or $value. $value = 0 also indicates that the file is not okay, but any value greater than 0 indicates that it is a valid SQLite file.
The point is that when I test this code manually inserting a path for $filedir, e.g a file already existing in this machine, the output is correct. But when I try to verify "$_FILES['upload_file']['tmp_name']" it doesn't work, and the page crashes.
I am new at web programming, especially in PHP, so I think there might be a misunderstanding about the $_FILE variable.
You should be able to check the mime type of the uploaded file:
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES['upload_file']['tmp_name']);
// SQLite is application/x-sqlite3
if ($mime == 'application/x-sqlite3') {
// Is SQLite
} else {
// Is something else
}

How to do file versioning when uploading files to Alfresco using CMIS PHP

I'm using the Apache Chemistry CMIS PHP client to upload documents from a local folder to Alfresco Community Edition 5.1 via ATOM. Here's the script I'm using to do so:
require_once ('cmis_repository_wrapper.php');
require_once ('cmis_service.php');
$repo_url = "http://127.0.0.1:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom";
$repo_username = "user";
$repo_password = "pass";
$client = new CMISService($repo_url, $repo_username, $repo_password);
$repo_folder = "/alfrescoFolder";
$source_folder = "localFolder/";
$source_files = array_diff(scandir("$source_folder", 1), array('..', '.'));
$myfolder = $client->getObjectByPath($repo_folder);
foreach($source_files as $file)
{
try
{
$upload = $client->createDocumentFromSource($myfolder->id, $file, "$source_folder/$file");
}
catch(Exception $e)
{
echo "Some error here.";
}
}
This script works fine and documents are uploaded without problem, provided that the document doesn't already exist in the Alfresco repository. For example, let's say I have a document in my Alfresco repository named example.txt, and so, if I try to upload a document from my local folder with the same name, I get a CMIS constraint exception. I dont't know how I can upload a new version of an existing document.
This is what I've tried so far, but it doesn't work:
$objs = $client->getChildren($myfolder->id);
foreach($source_files as $file)
{
foreach($objs->objectList as $obj)
{
if($obj->properties['cmis:name'] == $file)
{
try
{
$checkedout = $client->checkOut($obj->id);
$client->checkIn($checkedout->id);
}
catch(Exception $e)
{
echo "Some error here.";
}
}
else
{
try
{
$upload = $client->createDocumentFromSource($myfolder->id, $file, "$source_folder/$file", array('cmis:objectTypeId'=>'D:ex:document'));
}
catch(Exception $e)
{
echo "Some error here";
}
}
}
}
I get this error:
DEBUG: postEntry: myURL = http://127.0.0.1:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom/checkedoutDEBUG: postEntry: entry_template = {title} {SUMMARY} {CONTENT} {PROPERTIES} DEBUG: postEntry: properties_xml = b549c715-9a9d-427c-bd4b-c6ea29d222cb;1.0 DEBUG: postEntry: hash_values = Array ( [PROPERTIES] => b549c715-9a9d-427c-bd4b-c6ea29d222cb;1.0 [SUMMARY] => {summary} ) DEBUG: postEntry: post_value = b549c715-9a9d-427c-bd4b-c6ea29d222cb;1.0
What's funny is that the document is in fact locked for editing, so I don't really know what's going on. I also don't know if checking out and then checking in a document is how I'm supposed to version a document.
TL;DR
I want to be able to specify that the document I'm uploading is a new version of an existing document. Does anyone know how I can do that?
The function coverage page on the Apache Chemistry web site lists what the CMIS PHP client can and cannot do. Check out, check in, and cancel checkout are all unsupported at the present time. I know they would welcome contributions.
The underlying CMIS specification supports it, of course, so you can either update the library to support checkout/checkin or use the raw binding.
I'm not an expert on CMIS, but I think that this forum post answers the question. See the answer from "jevon" that provides an example and a link to this page (see the "Updating a document" section)
I've recently found out about an alternative CMIS PHP library that implements versioning services, including example usage. I've used it to successfully solve the problem I posted in my question.
Edit: additional information added.
So, to get versioning working, I used the example code provided in the library. The script I used can be used to create new documents and to update and version existing documents. So, here it is:
<?php
require_once(__DIR__ . '/../vendor/autoload.php');
if (!is_file(__DIR__ . '/conf/Configuration.php')) {
die("Please add your connection credentials to the file \"" . __DIR__ . "/conf/Configuration.php\".\n");
} else {
require_once(__DIR__ . '/conf/Configuration.php');
}
$major = (boolean) isset($argv[1]) ? $argv[1] : false;
$httpInvoker = new \GuzzleHttp\Client(
array(
'defaults' => array(
'auth' => array(
CMIS_BROWSER_USER,
CMIS_BROWSER_PASSWORD
)
)
)
);
$parameters = array(
\Dkd\PhpCmis\SessionParameter::BINDING_TYPE => \Dkd\PhpCmis\Enum\BindingType::BROWSER,
\Dkd\PhpCmis\SessionParameter::BROWSER_URL => CMIS_BROWSER_URL,
\Dkd\PhpCmis\SessionParameter::BROWSER_SUCCINCT => false,
\Dkd\PhpCmis\SessionParameter::HTTP_INVOKER_OBJECT => $httpInvoker,
);
$sessionFactory = new \Dkd\PhpCmis\SessionFactory();
// If no repository id is defined use the first repository
if (CMIS_REPOSITORY_ID === null) {
$repositories = $sessionFactory->getRepositories($parameters);
$repositoryId = $repositories[0]->getId();
} else {
$repositoryId = CMIS_REPOSITORY_ID;
}
$parameters[\Dkd\PhpCmis\SessionParameter::REPOSITORY_ID] = $repositoryId;
$session = $sessionFactory->createSession($parameters);
$rootFolder = $session->getObject($session->createObjectId($session->getRootFolder()->getId()));
try {
$document = null;
$stream = \GuzzleHttp\Stream\Stream::factory(fopen($filePath, 'r'));
foreach ($rootFolder->getChildren() as $child) {
if ($child->getName() === $fileName) {
$document = $child;
break;
}
}
if (!$document) {
$properties = array(
\Dkd\PhpCmis\PropertyIds::OBJECT_TYPE_ID => 'cmis:document',
\Dkd\PhpCmis\PropertyIds::NAME => $fileName
);
$document = $session->createDocument($properties, $rootFolder, $stream);
$document = $session->getObject($document);
}
$checkedOutDocumentId = $document->getVersionSeriesCheckedOutId();
if ($checkedOutDocumentId) {
$checkedOutDocumentId = $session->createObjectId($checkedOutDocumentId);
} else {
$checkedOutDocumentId = $document->checkOut();
}
$checkedInDocumentId = $session->getObject($checkedOutDocumentId)->checkIn(
$major,
array(
\Dkd\PhpCmis\PropertyIds::DESCRIPTION => 'New description'
),
$stream,
'Comments'
);
} catch (\Dkd\PhpCmis\Exception\CmisVersioningException $e) {
echo "********* ERROR **********\n";
echo $e->getMessage() . "\n";
echo "**************************\n";
exit();
}

Get a particular line of code executed "No Matter What"

Below is the code that throws some errors while getting executed. What I'm trying to do is the last line of the code gets executed no matter what (Error or no Error).
<?php
require 'main.php';
function create_photo($file_path) {
# Upload the received image file to Cloudinary
#$result = \Cloudinary\Uploader::upload($file_path, array(
"tags" => "backend_photo_album",
));
#unlink($file_path);
error_log("Upload result: " . \PhotoAlbum\ret_var_dump($result));
$photo = \PhotoAlbum\create_photo_model($result);
return $result;
}
$files = $_FILES["files"];
$files = is_array($files) ? $files : array($files);
$files_data = array();
foreach ($files["tmp_name"] as $index => $value) {
array_push($files_data, create_photo($value));
}
?>
<script>window.location.replace('index.html')</script>
Any help would be much appreciated. Thanks
I think depending on your php version, you can use a "try/catch/finally" bloc like that:
try
{
// code that may throw an exception
}
catch(Exeption $e) // The exception you want to catch
{
// Exception treatment
}
finally
{
// Executed no matter what
}
Maybe take a look about how to use that.

google drive PHP : how to list complete subtree of the folder

How to get basic info (id, title, mime-type at least) for each file and folder in subtree of given folder with as few API-calls as possible? ie. not to call api to download details for every subfolder?
I found the workaround to read all files with some non-hierarchical-characteristic (eg. owner) and to build tree-structure in client script. My files are unfortunately all from one owner (application), so I cannot do it this way.
ok, here is the example code for the recursion-multiple-api-calls way, which can be enough for some use cases. But I would like to find better concept (not to discuss this implementation, but another way, how to not call the API for each folder):
class Foo {
const FOLDER_MIME_TYPE = 'application/vnd.google-apps.folder';
public function getSubtreeForFolder($parentId, $sort=true)
{
$service = $this->createCrmGService();
// A. folder info
$file = $service->files->get($parentId);
$ret = array(
'id' => $parentId,
'name' => $file->getTitle(),
'description' => $file->getDescription(),
'mimetype' => $file->getMimeType(),
'is_folder' => true,
'children' => array(),
'node' => $file,
);
if ($ret['mimetype'] != self::FOLDER_MIME_TYPE) {
throw new Exception(_t("{$ret['name']} is not a folder."));
}
$items = $this->findAllFiles($queryString='trashed = false', $parentId, $fieldsFilter='items(alternateLink,description,fileSize,id,mimeType,title)', $service);
foreach ($items as $child)
{
if ($this->isFolder($child))
{
$ret['children'][] = $this->getSubtreeForFolder($child->id, $sort);
}
else
{
// B. file info
$a['id'] = $child->id;
$a['name'] = $child->title;
$a['description'] = $child->description;
$a['is_folder'] = false;
$a['url'] = $file->getDownloadUrl();
$a['url_detail'] = $child->getAlternateLink();
$a['versionLabel'] = false; //FIXME
$a['node'] = $child;
if (!$a['versionLabel']) {
$a['versionLabel'] = '1.0'; //old files compatibility hack
}
$ret['children'][] = $a;
}
}
if ($sort && isset($ret['children']))
{
if ($sort === true) {
$sort = create_function('$a, $b', 'if ($a[\'name\'] == $b[\'name\']) return 0; return strcasecmp($a[\'name\'], $b[\'name\']);');
}
usort($ret['children'], $sort);
}
return $ret;
}
public function findAllFiles($queryString, $parentId=false, $fieldsFilter='items(id,title)', $service = false)
{
if (!$service) $service = $this->createCrmGService();
$result = array();
$pageToken = NULL;
if ($parentId) {
$queryString .= ($queryString ? ' AND ' : '') . "'{$parentId}' in parents";
}
do {
try {
$parameters = array('q' => $queryString);
if ($fieldsFilter) $parameters['fields'] = $fieldsFilter;
if ($pageToken) {
$parameters['pageToken'] = $pageToken;
}
$files = $service->files->listFiles($parameters);
$result = array_merge($result, $files->getItems());
$pageToken = $files->getNextPageToken();
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
$pageToken = NULL;
}
} while ($pageToken);
return $result;
}
/**
* #param Google_DriveFile $file
* #return boolean, jestli je $file slozka.
*/
protected function isFolder($file)
{
return $file->getMimeType() == self::FOLDER_MIME_TYPE;
}
}
First, I would suggest you not to get all files and folders. It takes too much time for some users who have many files uploaded on their Drive. Also, there is query limit in your application key. In fact, many applications who have custom file picker make queries each time user requests subfolder.
Second, if this is webapp, it would be better idea to use Google Picker. Google Picker is way much faster and more efficient to pick files from Drive. There are many options and filters and you have decent control over files.
Third, you cannot fully represent Drive's files and folders in tree structure. As you can see in queries, each file have parents, which means there can be more than one parent for each file/folder. You need to think of some workarounds like choosing only one of the parents for each file.
If you still want to get all file/folder information, in terms of performance, the best implementation would be recursively calling Children.list(). FYI, file id 'root' is reserved id you can easily start with. And once you get id's of children, you can make batch query of Files.get() with multipart. This is the fastest way to traverse through file system of Google Drive afaik.
Again, unless you have very good reason, please do not try to traverse through all files in Drive at once. There are some users who have a lot of files in their Drive and you will make them wait forever no matter how great optimization you made. Also, you will easily hit query limit.

Categories