How can you use the ResourceWatcher bundle from YoSymfony? - php

I am trying to make a file watcher where, when you add, update or delete a file, you can see the files updates in a database. I'm using the framework Symfony4 and a bundle from it called ResourceWatcher from YoSymfony. This bundle uses the Finder bundle from Symfony to find files in the directories specified and then, the watcher compares the cache and the new file to see if there are any changes. When I use a method with the watcher which returns a path array, when I try to see the array, it returns null. How am I suppose to use these methods and their returns?
I put the var_dump everywhere to see that the problem comes from the findChanges()->getUpdatedFiles() and getNewFiles();
//OLD CODE
$finder = new Finder();
$finder->files()
->name('*.csv')
->in('%kernel.root_dir%/../src/data/');
//watcher
$hashContent = new Crc32ContentHash();
$resourceCache = new ResourceCachePhpFile('cache-key.php');
$watcher = new ResourceWatcher($resourceCache, $finder, $hashContent);
$watcher->initialize();
if($watcher->findChanges()->hasChanges()){
if($watcher->findChanges()->getNewFiles() === null){
$paths = $watcher->findChanges()->getUpdatedFiles();
}
else{
$paths = $watcher->findChanges()->getNewFiles();
}
$propertyAccessor = PropertyAccess::createPropertyAccessor();
var_dump($propertyAccessor->getValue($paths, '[first_name]'));
die();
}
I'd like to be able to see the paths, convert them into string and use that into my other method to make the data appear in my database.
In my var_dump, I get NULL in terminal.
EDIT:[first_name] is in my csv-file, you can dump $paths directly.
//NEW CODE
$finder = new Finder();
$finder->files()
->name('*.csv')
->in('%kernel.root_dir%/../src/data/');
//watcher
$hashContent = new Crc32ContentHash();
$resourceCache = new ResourceCachePhpFile('cache-key.php');
$watcher = new ResourceWatcher($resourceCache, $finder, $hashContent);
$watcher->initialize();
$changes = $watcher->findChanges();
if(!empty($changes->getUpdatedFiles())){
$updatedFilesPath = $changes->getUpdatedFiles();
$pathString = implode($updatedFilesPath);
$reader = Reader::createFromPath($pathString);
}
elseif(!empty($changes->getNewFiles())){
$newFilesPath = $changes->getNewFiles();
$pathString = implode($newFilesPath);
$reader = Reader::createFromPath($pathString);
}
else{
return;
}
$results = $reader->fetchAssoc();

So it looks like that as soon as you use the method findChanges()->hasChanges(), it tells the watcher that there is some changes but then it resets and there's no changes anymore in the watcher so it's pointless to use
$paths = $watcher->findChanges()->getUpdatedFiles();
since it will always return nothing because of the reset. I had to make a variable with the changes inside so that I could re-use the changes further down.
Details in code...

Related

How to get smarty file tokens?

How to get smarty(test.tpl) file tokens using the smarty-php/smarty-lexer package. From the documentation, I can’t understand how to do this, since I don’t have experience in parsing a file into tokens.
use Smarty_Internal_SmartyTemplateCompiler;
use Smarty_Internal_Templatelexer;
use Smarty;
use Smarty_Internal_Templateparser;
$smarty = new Smarty();
$templateSource = file_get_contents('path/to/template.tpl');
$lexer = new Smarty_Internal_Templatelexer();
$parser = new Smarty_Internal_Templateparser();
$compiler = new Smarty_Internal_SmartyTemplateCompiler($lexer, $parser, $smarty);
$lexer = new Smarty_Internal_Templatelexer($templateSource, $compiler);
$tokens = $lexer->tokenize();
This is one of the methods that I tried, I tried different approaches, nothing works.

Using the mikehaertl\php-pdftk library for manipulating PDFs, chaining commands fails when getDataFields is called first

I'm attempting to create a wrapper class around the mikehaertl\php-pdftk\pdf object for the purposes of populating PDF form fields. When trying to chain commands via the documentation the pdf fails to correctly execute the second command (or any after the first). It looks as though this is an issue with the underlying temp file handling and the tmep file not being written out as I watch my temp folder. As I debug, the temp file is there, but of 0 size.
Sample code demonstrating the issue
use mikehaertl\pdftk\Pdf;
class PDFTKTest extends TestCase
{
public function testPdfTkOperations()
{
$cmdPath = 'D:\PDFtk\bin\pdftk.exe';
$formPath = 'D:\test\sample_files\test.pdf';
$options = ['command' => $cmdPath];
$pdf = new Pdf($formPath, $options);
$this->assertNotNull($pdf);
//Get fields from PDF
$fields = $pdf->getDataFields();
$this->assertNotNull($fields);
//Set some field Values
$values = ['full_name' => 'John Q. Programmer'];
$pdf2 = new Pdf($pdf, $options); //chaining broken
//$pdf2 = new Pdf($formPath, $options); //works fine creating a new Pdf object
$this->assertNotNull($pdf2);
$res = $pdf2->fillForm($values)->execute();
//Next assertion fails using chaining
$this->assertTrue($res, "Execute failed: \n". $pdf2->getError());
//Get fields with the updates
$fields = $pdf2->getDataFields();
$this->assertNotNull($fields);
//Next assertion fails, getDataFields fails on a chained command
$this->assertGreaterThan(0, count($fields));
}
}
I've got a work around where I use separate \Pdf objects for each action and manage my own temp file, I was just hoping to take advantage of the classes functionality a bit more and not have to do so much of the mundane. Is this functionality broken, or am I using it incorrectly?
After looking deeper in to the PDFTK library which mikehaertl\php-pdftk\pdf wraps and reading the documentation on the dump_data_fields option I came up with the folowing observations:
PDFTK doesn't produce an output file for the dump_data_fields command
The php-pdftk class does create the underlying temp file when calling getDataFields, but it is empty and remains that way.
When chaining another Pdf object, it references the empty temp file from the previous command. Here lies the rub.
Solution
When I call getFieldData I create a new Pdf object and chain it to the previous, however I don't save a reference to that. I only save the newly chained object if it is form a command that creates actual output.
Here's an exmaple to demonstate:
<?php
use mikehaertl\pdftk\Pdf;
class PDFTKFormService
{
protected $pdf = null;
/**
* #return array|bool|\mikehaertl\pdftk\DataFields
*/
public function getDataFields()
{
//get data fields doesn't output a new file
//so we need to use the existing instance or create a new one and
$pdf = $this->getNextPdf();
$fields = $pdf->getDataFields();
if ($fields === false)
return [];
return $fields;
}
/**
* #param array $data
*
* #return resource The stream resource
*/
public function setDataFieldValues($data = [])
{
$this->pdf = $this->getNextPdf();
$this->pdf->fillForm($data)->execute();
}
protected function getNextPdf()
{
$options = ['command' => 'Path\To\PDFTK\binary'];
if ($this->pdf === null) {
return new Pdf($this->getTemplatePath(), $options);
} else {
return new Pdf($this->pdf, $options);
}
}
}
Hopefully this can help someone else.

How to generate entity id for GAE datastore in php?

i am trying to insert new entity using PHP client library into datastore, i am using datastore_connect.php file from this example, https://github.com/amygdala/appengine_php_datastore_example
I want to insert entity with auto id, not the name. I see that there is function setId(), but i dont know how to generate proper id. Whats the best practice in doing so?
Thanks
function createKeyForTestItem () {
$path = new Google_Service_Datastore_KeyPathElement();
$path->setKind("testkind");
$path->setName("testkeyname");
//$path->setId(??)
$key = new Google_Service_Datastore_Key();
$key->setPath([$path]);
return $key;
}
You can have Cloud Datastore generate the ID for you by populating the insertAutoId field on the mutation instead of the upsert field.
Here's a code snippet (adapted from the datastore_connect.php file you posted):
function create_key() {
$path = new Google_Service_Datastore_KeyPathElement();
$path->setKind("testkind");
// Neither name nor ID is set.
$key = new Google_Service_Datastore_Key();
$key->setPath([$path]);
return $key;
}
function create_entity() {
$entity = new Google_Service_Datastore_Entity();
$entity->setKey(create_key());
// Add properties...
return $entity;
}
function create_commit_request() {
$entity = create_entity();
$mutation = new Google_Service_Datastore_Mutation();
$mutation->setInsertAutoId([$entity]); // Causes ID to be allocated.
$req = new Google_Service_Datastore_CommitRequest();
$req->setMode('NON_TRANSACTIONAL');
$req->setMutation($mutation);
return $req;
}
If you're looking for a PHP library to take away most of the headache of Cloud Datastore, you could try my new library, which sits on top of the official google-api-php-client:
https://github.com/tomwalder/php-gds
And here's a sample code snippet to create an Entity with an auto-generated ID
$obj_book = new GDS\Entity();
$obj_book->title = 'Romeo and Juliet';
$obj_book->author = 'William Shakespeare';
$obj_book->isbn = '1840224339';
// Write it to Datastore
$obj_book_store->upsert($obj_book);
More code snippets and documentation on GitHub.

Instantiating all classes in directory

I'm using Laravel and creating artisan commands but I need to register each one in start/artisan.php by calling
Artisan::add(new MyCommand);
How can I take all files in a directory (app/commands/*), and instantiate every one of them in an array ? I'd like to get something like (pseudocode) :
$my_commands = [new Command1, new Command2, new Command3];
foreach($my_commands as $command){
Artisan::add($command);
}
Here is a way to auto-register artisan commands. (This code was adapted from the Symfony Bundle auto-loader.)
function registerArtisanCommands($namespace = '', $path = 'app/commands')
{
$finder = new \Symfony\Component\Finder\Finder();
$finder->files()->name('*Command.php')->in(base_path().'/'.$path);
foreach ($finder as $file) {
$ns = $namespace;
if ($relativePath = $file->getRelativePath()) {
$ns .= '\\'.strtr($relativePath, '/', '\\');
}
$class = $ns.'\\'.$file->getBasename('.php');
$r = new \ReflectionClass($class);
if ($r->isSubclassOf('Illuminate\\Console\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) {
\Artisan::add($r->newInstance());
}
}
}
registerArtisanCommands();
If you put that in your start/artisan.php file, all commands found in app/commands will be automatically registered (assuming you follow Laravel's recommendations for command and file names). If you namespace your commands like I do, you can call the function like so:
registerArtisanCommands('App\\Commands');
(This does add a global function, and a better way to do this would probably be creating a package. But this works.)
<?php
$contents = scandir('dir_path');
$files = array();
foreach($contents as $content) {
if(substr($content,0,1 == '.') {
continue;
}
$files[] = 'dir_path'.$content;
}
That reads the contents of a folder, itterates over it and saves the filename including path in the $files array. Hope this is what you're looking for
PS: Im not familiar with laravel or artisan. So if you have to use specific semantics(like camelCase) to register them, then please tell me so

How do i remove a file from Rackspace's Cloudfiles with their api?

I was wondering how do i remove a file from Rackspace's Cloudfiles using their API?
Im using php.
Devan
Use the delete_object method of CF_Container.
Here is my code in C#. Just guessing the api is similar for php.
UserCredentials userCredientials = new UserCredentials("xxxxxx", "99999999999999");
cloudConnection = new Connection(userCredientials);
cloudConnection.DeleteStorageItem(ContainerName, fileName);
Make sure you set the container and define any sudo folder you are using.
$my_container = $this->conn->get_container($cf_container);
//delete file
$my_container->delete_object($cf_folder.$file_name);
I thought I would post here since there isn't an answer marked as the correct one, although I would accept Matthew Flaschen answer as the correct one. This would be all the code you need to delete your file
<?php
require '/path/to/php-cloudfiles/cloudfiles.php';
$username = 'my_username';
$api_key = 'my_api_key';
$full_object_name = 'this/is/the/full/file/name/in/the/container.png';
$auth = new CF_Authentication($username, $api_key);
$auth->ssl_use_cabundle();
$auth->authenticate();
if ( $auth->authenticated() )
{
$this->connection = new CF_Connection($auth);
// Get the container we want to use
$container = $this->connection->get_container($name);
$object = $container->delete_object($full_object_name);
echo 'object deleted';
}
else
{
throw new AuthenticationException("Authentication failed") ;
}
Note that the "$full_object_name" includes the "path" to the file in the container and the file name with no initial '/'. This is because containers use a Pseudo-Hierarchical folders/directories and what end ups being the name of the file in the container is the path + filename. for more info see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Pseudo-Hierarchical_Folders_Directories-d1e1580.html
Use the method called DeleteObject from class CF_Container.
The method DeleteObject of CF_Container require only one string argument object_name.
This arguments should be the filename to be deleted.
See the example C# code bellow:
string username = "your-username";
string apiKey = "your-api-key";
CF_Client client = new CF_Client();
UserCredentials creds = new UserCredentials(username, apiKey);
Connection conn = new CF_Connection(creds, client);
conn.Authenticate();
var containerObj = new CF_Container(conn, client, container);
string file = "filename-to-delete";
containerObj.DeleteObject(file);
Note Don´t use the DeleteObject from class *CF_Client*

Categories