Error on Magmi after move to another server - magento

I just moved to another server and cannot reindex with Magmi, I receive the error below:
This script cannot be run from Browser. This is the shell script.
Thanks!

This error occurs when you run Magmi from the browser, because Magmi runs the indexer using shell_exec command, and the $_SERVER['REQUEST_METHOD'] doesn't get unset.
You can try one of two things.
Method 1. Unset the $_SERVER['REQUEST_METHOD'] variable Magento uses to check if the shell file is being run from the browser.
To do this, open magmi/plugins/base/general/reindex/magmi_reindexing_plugin.php
Find:
public function updateIndexes()
{
At the top of the updateIndexes() function, add the following:
if(isset($_SERVER['REQUEST_METHOD']))
{
unset($_SERVER['REQUEST_METHOD']);
}
So it will look like this:
public function updateIndexes()
{
if(isset($_SERVER['REQUEST_METHOD']))
{
unset($_SERVER['REQUEST_METHOD']);
}
Method 2: Modify the _validate() function in [magento_root]/shell/abstract.php
Open [magento_root]/shell/abstract.php
Find:
protected function _validate()
{
if (isset($_SERVER['REQUEST_METHOD'])) {
die('This script cannot be run from Browser. This is the shell script.');
}
}
Replace with:
protected function _validate()
{
if (isset($_SERVER['REQUEST_METHOD'])) {
//die('This script cannot be run from Browser. This is the shell script.');
}
}

Related

folder structure for scraping in Laravel, using Goutte

I am a bit confused about my folder structure for the scraping code. Using console/commands, not the controller. So, in the handle function I am writing the whole scraping code. But should I suppose to do that? Or... what is the best approach for this?
UPDATED
If I understand correctly the answer below. It should look like this right now.
calling services
class siteControl extends Command
{
protected $signature = 'bot:scrape {website_id}';
protected $description = 'target a portal site and scrape';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$website_id = $this->argument("website_id");
if ($website_id == 1) {
$portal = "App\Services\Site1";
}
$crawler = new $portal;
$crawler->run();
}
}
in handle method
class Site1 extends Utility
{
public function __construct()
{
parent::__construct();
}
public function run()
{
echo "method runs";
}
}
abstract:
use Goutte\Client;
abstract class Utility implements SiteInterfaces
{
protected $client;
public function __construct()
{
$this->client = new Client();
}
}
interfaces:
namespace App\Services;
interface SiteInterfaces
{
public function run();
}
and finally, I should write the whole scraping code inside the run() method? Please correct me If wrong about this... I am searching the best solution.
A best practice would be to call a separate service from your command handle() method. That way you could reuse that same service in a controller for instance.
The technical version:
Your application is given a specific thing to do (a command if you will). This command comes from outside of your application, which can be a anything from a web controller, to an API controller or a CLI application. In terms of hexagonal architecture this is called a port.
Once the application receives such a command it should not care which port it came from. By handling all similar commands in a single spot (a command handler) it does not have to worry about the origins of the command.
So to give you a short overview:
[Web request] [CLI command] <-- these are ports
\ /
\ /
\ /
[Command] <--- this is a method call to your service
|
|
|
[Command handler] <--- this is the service doing the actual work
Updated my answer
Based on the code you provided I implemented what I mentioned above like so:
app/Console/Command/BotScrapeCommand.php
This is the CLI command I mentioned above. All this class has to do is:
1. Gather input arguments; (website_id) in this case
2. Wrap those arguments in a command
3. Fire off the command using the command handler
namespace App\Console\Commands;
use App\Command\ScrapePortalSiteCommand;
use CommandHandler\ScrapePortalSiteCommandHandler;
class BotScrapeCommand extends Command
{
protected $signature = 'bot:scrape {website_id}';
protected $description = 'target a portal site and scrape';
public function handle(ScrapePortalSiteCommandHandler $handler)
{
$portalSiteId = $this->argument("website_id");
$command = new ScrapePortalSiteCommand($portalSiteId);
$handler->handle($command);
}
}
app/Command/ScapePortalSiteCommand.php
This is the Command I mentioned above. Its job is to wrap all input arguments in a class, which can be used by a command handler.
namespace App\Command;
class ScrapePortalSiteCommand
{
/**
* #var int
*/
private $portalSiteId;
public function __construct(int $portalSiteId)
{
$this->portalSiteId = $portalSiteId;
}
public function getPortalSiteId(): int
{
return $this->portalSiteId;
}
}
app/CommandHandler/ScrapePortalSiteCommandHandler.php
The command handler should implement logic based on its command. In this case that's figuring out which crawler to pick, then fire that one off.
namespace App\CommandHandler;
use App\Command\ScrapePortalSiteCommand;
use App\Crawler\PortalSite1Crawler;
use App\Crawler\PortalSiteCrawlerInterface;
use InvalidArgumentException;
class ScrapePortalSiteCommandHandler
{
public function handle(ScrapePortalSiteCommand $command): void
{
$crawler = $this->getCrawlerForPortalSite($command->getPortalSiteId());
$crawler->crawl();
}
private function getCrawlerForPortalSite(int $portalSiteId): PortalSiteCrawlerInterface {
switch ($portalSiteId) {
case 1:
return new PortalSite1Crawler();
default:
throw new InvalidArgumentException(
sprintf('No crawler configured for portal site with id "%s"', $portalSiteId)
);
}
}
}
app/Crawler/PortalSiteCrawlerInterface.php
This interface is there to make sure all crawlers can be called in similar fashion. Additionally it makes for nice type hinting.
namespace App\Crawler;
interface PortalSiteCrawlerInterface
{
public function crawl(): void;
}
app/Crawler/PortalSite1Crawler.php
This is where the implementation of the actual scraping goes.
namespace App\Crawler;
class PortalSite1Crawler implements PortalSiteCrawlerInterface
{
public function crawl(): void
{
// Crawl your site here
}
}
Another update
As you had some additional questions I've updated my answer once more.
:void
The use of : void in a method declaration means the method will not return anything. In a same way public function getPortalSiteId(): int means this method will always return an integer. The use of return typehints was added to PHP 7 and is not specific to Laravel. More information on return typehints can be found in the PHP documentation.
Commands and handlers
The use of commands and command handlers is a best practice which is part of the command bus pattern. This pattern describes an universal way of dealing with user input (a command). This post offers a nice explanation on commands and handlers. Additionally, this blog post describes in more details what a command bus is, how it's used and what the advantages are. Please note that in the code I've provided the bus implementation itself is skipped. In my opinion you do not need it per se, but in some cases it does add value.

How to get unit test results in the browser with Laravel.

I would like to see the results of individual unit tests in the browser. I would like to do something like...
public function test() {
$test = new \Tests\Unit\ExampleTest();
dd($test->testBasicTest());
}
That just returns null. I also tried exec('vendor/bin/phpunit'); but would like to stay away from exec() (and to mention, that snippet creates an endless loop for some reason).
What if you try doing a echo of your dd?
public function test() {
$test = new \Tests\Unit\ExampleTest();
echo(dd($test->testBasicTest()));
}

writing output to a file with CakePHP shell

I am trying to just simply write "hello world" to a file, from a cakephp shell, with plans to eventually write a sitemap.xml file using our product models. I found this: Question which got me started...
But i am thinking either ConsoleOutput is not supported in Cake 1.3.6 (which i'm using), or i need to include the class that holds it.
The error i get when trying to run the file from terminal:
PHP Fatal error: Class 'ConsoleOutput' not found in /public/vendors/shells/sitemap.php on line 7
Here is my code:
class SitemapShell extends Shell {
public function __construct($stdout = null, $stderr = null, $stdin = null) {
// This will cause all Shell outputs, eg. from $this->out(), to be written to
// TMP.'shell.out'
$stdout = new ConsoleOutput('file://'.TMP.'shell.out');
// You can do the same for stderr too if you wish
// $stderr = new ConsoleOutput('file://'.TMP.'shell.err');
parent::__construct($stdout, $stderr, $stdin);
}
public function main() {
// The following output will not be printed on your console
// but be written to TMP.'shell.out'
$this->out('Hello world');
}
}
You are correct that ConsoleOutput didn't feature in CakePHP 1.3 - can you upgrade to a version 2.*?
If not you could just use regular PHP:
$fp = fopen('hello.txt', 'w');
fwrite($fp, 'hello world');
fclose($fp);
Hope this helps.
Toby

Cake 2.0 CLI mode error "Undefined HTTP_HOST "

I am Running a shell script on cake console. Able to run HelloShell But getting error undefined HTTP_host on app/config/core.php for following code:
class HelloShell extends AppShell {
public $uses=array('Test');
public function main() {
$this->out('Hello Kundan.');
}
public function hey() {
$this->Test->save($data['Test']['name']='Kundan');
}
}
bellow the error message:
PHP notice: undefined index HTTP_HOST in
C:\wamp\www\myapplication\app\Config\core.php on line 231.
When I opened that file I found following on line number 231 Configure::write('Website_root',$_SERVER['HTTP_HOST']);
I have replicate your code, and it run well.
where do you put HelloShell.php file? and how do you run your code?.
The common way, put your HelloShell.php file in app/Console/Command/ directory and run it by Console/cake hello
also try to modify your code:
class HelloShell extends AppShell {
public $uses=array('Test');
public function main() {
$this->out('Hello Kundan.');
$this->hey();
}
public function hey() {
$data['Test']['name']='Kundan';
$this->Test->save($data);
}
}

Dynamics AX 2009: Batch Trouble with AsciiIO class

I have a custom class, we'll call it FileProcessUpload and it extends RunBaseBatch. It more or less creates a CSV file and then uploads it to an FTP server. When the class is run manually, everything works fine. However, when submitted as a Batch Job, there is an error in the infolog stating "AsciiIO object not initialized".
Probably the most important thing to note here is that this Batch Job is being delegated to a different AOS.
Here is a cropped down version of the offending code:
void CreateFiles()
{
#File
AsciiIO asciiio;
FileIOPermission permission;
ATable aTable;
str outputFile;
str directory;
;
directory = #'C:\Uploads';
ouptutFile = directory + #'\output.csv';
if (!WinAPI::folderExists(directory))
{
WinAPI::createDirectory(directory);
}
// Try to assert the appropriate file access mode
permission = new FileIOPermission(outputFile, #io_write);
permission.assert();
// Try to open the file for writing
asciiio = new AsciiIO(outputFile, #io_write);
if (asciiio != null)
{
while select aTable
{
// Write the necessary lines into the file
asciiio.write(aTable.field1 + ',' + aTable.field2);
}
}
else
{
error('Could not create file: ' + outputFile);
}
// Close file and release permission assertion
asciiio = null;
CodeAccessPermission::revertAssert();
}
Does the service user that Ax is running under have permissions to read/write the file?
You are using the WinAPI class, but should you be using WinAPIServer class instead? You may be executing on the server of course.
Do you need to add to your class the following public boolean runsImpersonated() { return false; } and run this class on a client?
Good luck
Edit: Executing your code via the server static void mainOnServer(Args args) method signature is commonly used (see PurchFormLetter class for it's usage) to make sure that you execute on the server. It is called from static void main(Args args)
Use file path and file name instead of str as directory and name
If runbasebatch then should put pack/uppack filePath and fileName and put it into currentVersion control at classdeclaration.
If you move/delete/encrytion/read file, using system.io.file /system.io.stream, or streamreader, or system.net.ftpwebrequest, and system.net.ftpwebresponse, remember to run on server static void method for this...
Any file format I have done, txt, .csv, .gpg, I move around file easily in/out ax to other server, no problem to just write a file inside of AX by fellowing the above rule..

Resources