How to make a 'npm run build' from a symfony project - php

I currently have a symfony project that uses Foundation for Emails to create responsive emails.
The Foundation framework uses the command 'npm run build' to tranform files. I tried doing a service parse my content using the Process class but I must be using it wrong as it does not execute 'npm run build'. Here is my faulty code :
<?php
/**
* Created by PhpStorm.
* User: jeremie
* Date: 28/12/17
* Time: 16:59
*/
namespace Acme\Open4XMLParserBundle\Services;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\Process;
/**
* #todo : code this
*/
class FoundationParser
{
protected $foundationLocation;
protected $process;
/**
* FoundationParser constructor.
* #param $foundationLocation
*/
public function __construct($foundationLocation)
{
$this->foundationLocation = $foundationLocation;
$this->process = new Process('npm run build', $this->foundationLocation);
}
/**
* Run npm run build if needed
*/
public function initFoundation()
{
//make sure that 'npm run build' is running and execute it if not
if (!$this->process->isRunning()) {
$this->process->start();
}
}
public function saveFoundationContent($foundationContent, $filename)
{
//save the file in foundation/src/pages
$fileSystem = new Filesystem();
$fileLocation = $this->foundationLocation . '/src/pages/' . $filename;
if (!$fileSystem->exists($fileLocation)) {
$fileSystem->dumpFile($fileLocation, $foundationContent);
$fileSystem->chmod($fileLocation, 0664);
}
}
public function retrieveValidHtml($fileName)
{
$fileLocation = $this->foundationLocation . '/dist/' . $fileName;
while (true) {
try {
$result = file_get_contents($fileLocation);
if ($result !== false){
return $result;
}
} catch (\Exception $e) {
}
}
}
}
And I use my service like this :
$foundationParser = $this->container->get('open4xmlparser.foundationparser');
$foundationParser->initFoundation();
$foundationParser->saveFoundationContent($foundationContent, 'test.html');
$response = new Response($foundationParser->retrieveValidHtml('test.html'));
$response->headers->set('Content-Type', 'text/html');
$response->send();
And it tells me that 'test.html' does not exist. Any idea on how to do what I want?

What I finally decided to do is a Symfony command that launch my program in an infinite loop(it is never supposed to stop). Instead of using a service I executed 'npm run build' directly in the while loop.
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln([
'',
'Running program',
'===============',
''
]);
$runBuild = new Process('npm run build', $this->getContainer()->getParameter('foundation_location'));
while (true) {
if (!$runBuild->isRunning()){
$output->writeln([
'',
'Executing npm run build',
''
]);
$runBuild->start();
}
}
}

You seem to have different paths in the saveFoundationContent and retrieveValidHtml for the target file.
// saveFoundationContent()
$fileLocation = $this->foundationLocation . '/src/pages/' . $filename;
// retrieveValidHtml()
$fileLocation = $this->foundationLocation . '/dist/' . $fileName;
Obviously, retrieveValidHtml() cannot find the file in the location.
Tip: Store the subdirectory path as a class variable (or constant):
class FoundationParser
{
private $subdir = "/dist/"; // or "/src/pages/";
…
public function retrieveValidHtml($fileName)
{
$fileLocation = sprintf("%s%s%s", $this->foundationLocation, $this->subdir, $fileName);
…
}
}

Related

PHP Longman telegram bot. Can't download files via webhooks

I'm using longman/telegram-bot package at my Yii2 project.
class GenericmessageCommand extends SystemCommand
{
/**
* #var string
*/
protected $name = 'genericmessage';
/**
* #var string
*/
protected $description = 'Handle generic message';
/**
* #var string
*/
protected $version = '1.0.0';
/**
* Main command execution
*
* #return ServerResponse
*/
public function execute(): ServerResponse
{
$message = $this->getMessage();
if (in_array($message->getType(), ['audio', 'document', 'photo', 'video', 'voice'])) {
$doc = call_user_func([$message, 'get' . $message->getType()]);
($message->getType() === 'photo') && $doc = end($doc);
$photoId = $doc->file_id;
$download_path = $this->telegram->getDownloadPath();
$file = Request::getFile(['file_id' => $photoId]);
if ($file->isOk() && Request::downloadFile($file->getResult())) {
return $this->replyToChat(' file is located at: ' . $download_path . '/' . $file->getResult()->getFilePath());
} else {
return $this->replyToChat('Failed to download.');
}
}
}
}
Just like that
It working fine when I'm using getUpdates method https://github.com/php-telegram-bot/core#getupdates-installation
But it doesn't work when I use WebHooks. Even though I get the same answer from my bot... It says "Ok" and "file is located at...", but there is no such file.
that because of webhook using backend of Yii2 advanced.... it stores all files at backend (because my webhook looking on backend), but i searching them at frontend (bacause i'm stupid).

Symfony ClassLoader or PHP autoload ca't find class after programmatic src code changes

This is an app that's intended to generate entities, allowing the end user to define the fields, and it worked like charm, until Sf 2.3 and PHP version something(don't recall the version that was running) on a debian 7. But now it's on a FreeBSD with PHP 5.4.28 and SF 2.4
It can create an entity from scratch or recreate and overwrite it with changes.. but all of a suden, the autoloader stopped (re-)loading the class after it's created. It wont be until next postback, that it actually sees the class, obviously if I don't create it again (e.g. commenting code).
So, The question is How can I force autoload of a class whose code had been written and saved to the class' php file during the request handling..?
The following code gives class not found.
/**
* Handles creation of the Doctrine Entity that will represent de Document being
* created.
*
* #param DocumentType $docDefinition The Document definition
*
* #return string Genedated Document's class shortcut notation.
*
* #throws \Exception if {#link $this->doctrineGenEntityCmd}->run() fails or throws
*/
protected function createDocumentEntity(DocumentType $docDefinition)
{
$this->log->info("Creating Document entity");
try {
list($exitCode, $out) =
$this->runCommand('generate:doctrine:entity', $this->generateEntityCmd, $docDefinition);
} catch (\Exception $exc) {
throw new \Exception(
sprintf("Can't create Document due to following: \n %s", $exc->getTraceAsString()),
null,
$exc
);
}
if (0 != $exitCode) {
throw new \Exception(
sprintf("Can't create Document due to following: \n %s", $out->getErrorOutput())
);
}
$justToAutoload = $this->tryInstantiate($docDefinition);
$this->log->info($justToAutoload);
return InputHandler\InputHandler::getClassShortcutNotation($docDefinition);
}
Inside the debugging fn tryInstantiate() I tried several things, unregistering autoloaders, re-including composer's (app/autoload.php)
protected function tryInstantiate(DocumentType $docDefinition)
{
$fqcn = "\\" . $this->getDocumentFqcn($docDefinition);
$log = $this->log;
$functions = spl_autoload_functions();
foreach($functions as $function) {
spl_autoload_unregister($function);
}
$newLoader = include $this->kernel->getRootDir() . '/autoload.php';
$newLoader->register(true);
$log->info('tryInstantiate');
// spl_autoload_register(function ($className) use ($fqcn, $log) {
// if ($className == $fqcn) {
// $log->info("Loading: " . $className);
// $baseDir = $this->kernel->getRootDir() . '/../src';
// $classFile = $baseDir . str_replace('\\', DIRECTORY_SEPARATOR , $fqcn) . '.php';
// include $classFile;
// }
// }, true, true);
//$fqcn = str_replace('\\', '\', $fqcn);
return $test = new \DocDigital\Bundle\DocumentBundle\Entity\CustomDocument\Test();
die(var_dump($test));
return new $fqcn();
try {
return $deletMe = new \DocDigital\Bundle\DocumentBundle\Entity\CustomDocument\Test1();
return new $fqcn();
} catch (\Exception $exc) {
sprintf("Can't instantiate %s due to the following: \n %s", $fqcn, $exc->getTraceAsString());
}
}
always with the same result:
php.CRITICAL: Fatal Error: Class 'bundle\Entity\namespace\Test' not found
Any help is appreciated.
Thanks!

Owncloud 8.1 "myapp" sample, add a function to write to a file

On Owncloud 8.1 using the owncloud command line, I create a new test app:
ocdev startapp MyApp --email mail#example.com --author "Your Name" --description "My first app" --owncloud 8
The app is working, I can add it in the owncloud control panel.
Now I'd like to write to a file, so I use one example from the owncloud documentation:
https://doc.owncloud.org/server/8.1/developer_manual/app/filesystem.html
[Edit] I started over and now, I don't know if I omitted something, but "myapp" comes with no "application.php" file.
So I create it at /var/www/core/apps/myapp/appinfo/application.php :
<?php
namespace OCA\MyApp\AppInfo;
use \OCP\AppFramework\App;
use \OCA\MyApp\Storage\AuthorStorage;
class Application extends App {
public function __construct(array $urlParams=array()){
parent::__construct('myapp', $urlParams);
$container = $this->getContainer();
/**
* Storage Layer
*/
$container->registerService('AuthorStorage', function($c) {
return new AuthorStorage($c->query('RootStorage'));
});
$container->registerService('RootStorage', function($c) {
return $c->query('ServerContainer')->getRootFolder();
});
}
}
Then I create a file called /var/www/core/apps/myapp/storage/AuthorStorage.php with:
<?php
namespace OCA\MyApp\Storage;
class AuthorStorage {
private $storage;
public function __construct($storage){
$this->storage = $storage;
}
public function writeTxt($content) {
// check if file exists and write to it if possible
try {
try {
$file = $this->storage->get('/myfile.txt');
} catch(\OCP\Files\NotFoundException $e) {
$this->storage->touch('/myfile.txt');
$file = $this->storage->get('/myfile.txt');
}
// the id can be accessed by $file->getId();
$file->putContent($content);
} catch(\OCP\Files\NotPermittedException $e) {
// you have to create this exception by yourself ;)
throw new StorageException('Cant write to file');
}
}
}
The sample app already gives me a route to the index function in the pagecontroller.php
['name' => 'page#index', 'url' => '/', 'verb' => 'GET']
How do I call the function "writeTxt" from there?
Based on http://php.net/manual/en/language.oop5.basic.php
I tried:
use \OCA\MyApp\Storage\AuthorStorage;
and
public function index() {
//added part
$a = new AuthorStorage();
$a->writeTxt('test');
//original part
$params = ['user' => $this->userId];
return new TemplateResponse('myapp', 'main', $params); //templates/main.php
}
After running I get a "Class 'OCA\MyApp\Storage\AuthorStorage' not found at /var/www/core/apps/myapp/controller/pagecontroller.php#44"
Even with the help of use \OCA\MyApp\Storage\AuthorStorage; ( ClassNotFoundException: Attempted to load class... Symfony ) it doesn't seem to help.
Thanks
Time has gone by, so I'm posting an answer to my question for owncloud 9.
Here are the steps to a basic script with read, write, copy file ability.
"application.php" has definitively been removed from the example. It was not a bug.
Following:
https://doc.owncloud.org/server/9.0/developer_manual/app/startapp.html
Generate the demo "MyApp" app:
ocdev startapp MyApp --email mail#example.com --author "Your Name" --description "My first app" --owncloud 9
Edit the file myapp/controller/pagecontroller.php
<?php
/**
* ownCloud - myapp
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* #author Your Name <mail#example.com>
* #copyright Your Name 2016
*/
namespace OCA\MyApp\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCP\Files\IRootFolder;
use OC\Files\Storage\Temporary;
class PageController extends Controller {
private $userId;
private $storage;
private $userstorage;
public function __construct($AppName, IRequest $request, IRootFolder $storage, $UserId){
parent::__construct($AppName, $request);
$this->storage = $storage;
$this->userId = $UserId;
$this->userstorage = $this->storage->get($this->userId.'/files/');
}
/**
* CAUTION: the #Stuff turns off security checks; for this page no admin is
* required and no CSRF check. If you don't know what CSRF is, read
* it up in the docs or you might create a security hole. This is
* basically the only required method to add this exemption, don't
* add it to any other method if you don't exactly know what it does
*
* #NoAdminRequired
* #NoCSRFRequired
*/
public function index() {
$listedudossier = $this->userstorage->getDirectoryListing();
//list all items in the root directory
//and copies the files in an directory called old
//the directory "old" is not script created
foreach ($listedudossier as $value) {
if ( $value->getType() == 'file' ){
$value->copy($this->userId.'/files/old/'.$value->getName());
//also works
//$value->copy($this->userstorage->getPath().'/old/'.$value->getName());
}
}
$params = ['listedudossier' => $listedudossier ];
return new TemplateResponse('myapp', 'main', $params); // templates/main.php
}
/**
* Simply method that posts back the payload of the request
* #NoAdminRequired
*/
public function doEcho($echo) {
//creates a file
$this->userstorage->newFile('myfile2.txt');
//opens a file, adds inputbox content and saves the file
$file = $this->userstorage->get('myfile.txt');
$contenu = $file->getContent();
$file->putContent($contenu.$echo);
return new DataResponse(['echo' => $echo]);
}
}
You also need to edit the myapp/templates/part.content.php
<p>Hello World <?php p($_['user']) ?></p>
<p><button id="hello">click me</button></p>
<p><textarea id="echo-content">
Send this as ajax
</textarea></p>
<p><button id="echo">Send ajax request</button></p>
Ajax response: <div id="echo-result"></div>
<p>listedudossier:<p> <?php
foreach ($_['listedudossier'] as $file) {
echo "type:".$file->getType();
echo "<p>";
echo "nom:".$file->getName();
echo "<p>";
echo "modif:".$file->getMTime();
echo "<p>";
}
From here you can test the code in a development environment:
https://github.com/owncloud/ocdev/blob/master/README.rst#installation

php app / console stops working

After a slight modification of my units, I wanted the update with a simple php app/console doctrine: update --force. But no action executed and in addition no response. I then did a php app/check.php meaning me no problems (Your system is ready to run Symfony2 projects). I do not understand and it doesn't provide an error. Here's what I've done:
Command: ********: ***** ProjetSymphony $ php app / console***
Answer (none): ******* **** $ ProjetSymphony***
If someone has an idea.
Screen :
Try with:
php app/console doctrine:schema:update --force
Maybe it's only a syntaxis error.
Also, if anyone tries to run php app/console in a newer symfony version (for example symfony 3.0), you will get an error: no file found because the file was moved to 'bin' folder. Now to run from the console, you have to use php bin/console instead. Just in case this change confused anyone who started to learn symfony and updated to 3.0.
I finally found my mistake. I had a command file that prevented the execution of my order (CreateUserCommand.php)
If someone wants to explain to me why this cosait file an error during the execution of my order ...
Here is the file :
<?php
namespace FP\UserBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use FOS\UserBundle\Model\User;
use FOS\UserBundle\Command\CreateUserCommand as BaseCommand;
class CreateUserCommand extends BaseCommand
{
/**
* #see Command
*/
protected function configure()
{
exit;
echo "tes";
parent::configure();
$this
->setName('fp:user:create')
->getDefinition()->addArguments(array(
new InputArgument('age', InputArgument::REQUIRED, 'The age')
))
;
}
/**
* #see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
exit;
echo "tes";
$username = $input->getArgument('username');
$email = $input->getArgument('email');
$password = $input->getArgument('password');
$age = $input->getArgument('age');
$inactive = $input->getOption('inactive');
$superadmin = $input->getOption('super-admin');
$manipulator = $this->getContainer()->get('fos_user.util.user_manipulator');
$manipulator->setAge($age);
$manipulator->create($username, $password, $email, !$inactive, $superadmin);
$output->writeln(sprintf('Created user <comment>%s</comment>', $username));
}
/**
* #see Command
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
exit;
echo "tes";
parent::interact($input, $output);
if (!$input->getArgument('age')) {
$age = $this->getHelper('dialog')->askAndValidate(
$output,
'Please choose a age:',
function($age) {
if (empty($age)) {
throw new \Exception('Lastname can not be empty');
}
return $age;
}
);
$input->setArgument('age', $age);
}
}
}

php zip include only new files

I've run into an issue with the php zip library causing an error 500 if the file is growing to larger than 500MB, probably memory related...
But I tried to cmd line the zip creation, which works well on my server.
<?php
set_time_limit(10000);
// Make Zip name
$zipname = "main_backup.zip";
// Make a zip file
$cmd = `zip -r $zipname * -x filelist.php -x $zipname`;
if($cmd){
echo 'zip created';
}
else{
echo 'failed';
}
unlink(__FILE__);
?>
I know how to exclude files and folders, but is there a way to zip only files based on the modified time using this approach?
I've googled for hours and came up empty.
for the sake of it, here's the code that was creating the error 500. My site is about 1.8GB, it always errors at 500MB~. I should note the error log is blank, so the cause of the error I'm just assuming to be RAM limit problems.
<?php
$zip = new ZipArchive;
$zip_name = "test.zip";
$res = $zip->open($zip_name, ZipArchive::CREATE);
/**
* Real Recursive Directory Iterator
*/
class RRDI extends RecursiveIteratorIterator {
/**
* Creates Real Recursive Directory Iterator
* #param string $path
* #param int $flags
* #return DirectoryIterator
*/
public function __construct($path, $flags = 0) {
parent::__construct(new RecursiveDirectoryIterator($path, $flags));
}
}
/**
* Real RecursiveDirectoryIterator Filtered Class
* Returns only those items which filenames match given regex
*/
class AdvancedDirectoryIterator extends FilterIterator {
/**
* Regex storage
* #var string
*/
private $regex;
/**
* Creates new AdvancedDirectoryIterator
* #param string $path, prefix with '-R ' for recursive, postfix with /[wildcards] for matching
* #param int $flags
* #return DirectoryIterator
*/
public function __construct($path, $flags = 0) {
if (strpos($path, '-R ') === 0) { $recursive = true; $path = substr($path, 3); }
if (preg_match('~/?([^/]*\*[^/]*)$~', $path, $matches)) { // matched wildcards in filename
$path = substr($path, 0, -strlen($matches[1]) - 1); // strip wildcards part from path
$this->regex = '~^' . str_replace('*', '.*', str_replace('.', '\.', $matches[1])) . '$~'; // convert wildcards to regex
if (!$path) $path = '.'; // if no path given, we assume CWD
}
parent::__construct($recursive ? new RRDI($path, $flags) : new DirectoryIterator($path));
}
/**
* Checks for regex in current filename, or matches all if no regex specified
* #return bool
*/
public function accept() { // FilterIterator method
return $this->regex === null ? true : preg_match($this->regex, $this->getInnerIterator()->getFilename());
}
}
foreach (new AdvancedDirectoryIterator('-R *') as $i){
//$fullpath = str_replace(',','',$i->getPath()).'/'.$i->getFilename();
//echo $fullpath.'<br />';
if ($i->isFile() && $i->getFilename()!='filelist.php') {
//echo $i->getFilename() . " " . $i->getMTime() . "<br />";
if($i->getMTime()>='0'){
$array[] = substr($i->getPathname(), 2);
}
}
};
// will output all php files in CWD and all subdirectories
foreach($array as $files) {
$zip_array[] = files;
$zip->addFile($files);
}
$zip->close();
echo 'done';
?>
You can use the -t or -tt option for the zip command and have your modifed date stored as a variable or just pass one in.
-t with the format mmddyyyy for from-date
-tt with the format mmddyyyy for before-date
//Zips up all files in current directory that were dated 08152013 or later
zip -r -t 08152013 $zipname * -x filelist.php -x $zipname

Categories