PHPUnit tests fail on writing file - phpunit

My unit tests are failing on Travis CI, but not locally.
https://travis-ci.org/humanmade/backupwordpress/jobs/43609663#L362
Error message:
1) testBackupPathTestCase::testMergeExistingPath
RuntimeException: Error writing to file. (/tmp/wordpress/wp-content/backupwordpress- a74dcf0e84-backups/.schedule-test-merge-existing-path-running)
Test is here:
https://github.com/humanmade/backupwordpress/blob/hmbkp-path/tests/other/testBackupPath.php#L135
That exception is thrown by the following function:
/**
* Set the status of the running backup
*
* #access public
*
* #param string $message
*
* #return void
*/
public function set_status( $message ) {
$status = json_encode( (object) array(
'filename' => $this->get_archive_filename(),
'started' => $this->get_schedule_running_start_time(),
'status' => $message,
) );
if ( false === #file_put_contents( $this->get_schedule_running_path(), $status ) ) {
throw new RuntimeException( sprintf( __( 'Error writing to file. (%s)', 'backpwordpress' ), $this->get_schedule_running_path() ) );
}
}
See full class here :
https://github.com/humanmade/backupwordpress/blob/hmbkp-path/classes/class-schedule.php#L838
How can I determine if it's an error caused by the CI environment, or a bug in the code?

Related

Getting customer adress in custom shipping method

I'm currently working on a custom shipping method for WooCommerce. The goal is to calculate the shipping based on the adress the customer enters in the order process. We currently have an API that receives a storeId and the adress of a customer and returns back the exact amount of shipping we need to apply to the order.
For this, I've started to write a new custom shipping order plugin. I am already receiving the $packages array with the order, however I can't seem to find a way to receive the customers adress in the calculate_shipping method. There also will be a useraction required to select the prefered warehouse on the reviewOrderBeforePayment page and I am not quite sure how to access that data yet.
<?php
/*
* Plugin Name: Warehouses Integration
* Description: WooCommerce integration of the Warehouses API
* Version: 1.1.0
* Author: -
* Author URI: -
* Developer: Laura Heimann
* Developer URI: -
* Text Domain: woocommerce-extension
* WC requires at least: 4.0.1
* WC tested up to: 4.0.1
*/
// Security Measure
if (!defined('ABSPATH')) {
exit;
}
// Check if WooCommerce is installed
if (!in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option( 'active_plugins')))) {
alert("WooCommerce is not installed!");
}
// Main Render Function
// This will be hooked into the WooCommerce Order Page
function wcfw_render() {
// TODO: Show List of possible stores, let user select and save selected store somehow
echo "WCFWRENDER";
}
function wcfw_renderThankYou() {
echo "WCFWTHANKYOU";
}
function wcfw_renderReviewOrder() {
// TODO: Show warning if items from different stores
echo "WCFWREVIEWORDER";
}
function wcfw_shippingMethodInit() {
if ( ! class_exists( 'WC_WCFW_Shipping_Method' ) ) {
class WC_WCFW_Shipping_Method extends WC_Shipping_Method {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
public function __construct() {
$this->id = 'wcfw_shipping_method';
$this->title = __( 'Warehouses Shipping' );
$this->method_description = __( 'Shipping Method through the Warehouse' );
$this->enabled = "yes";
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
$this->init_settings(); // This is part of the settings API. Loads settings you previously init.
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* Settings
*/
function init_form_fields() {
$this->form_fields = array(
'apiBase' => array(
'title' => __('Api Base'),
'type' => 'text',
'description' => __('The base URL for API-Calls.'),
'default' => __('---')
),
);
}
/**
* calculate_shipping function.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping( $package = array() ) {
var_dump( $package );
// TODO: Get Customers Adress and selected store
// TODO: Send data to API and apply provided shipping
$rate = array(
'label' => __('Shipping by Truck'),
'cost' => '10.99',
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate( $rate );
}
}
}
}
function add_wcfw_shipping_method( $methods ) {
$methods[] = 'WC_WCFW_Shipping_Method';
return $methods;
}
// Hooks
add_action('woocommerce_review_order_before_payment', 'wcfw_render', 10);
add_action('woocommerce_thankyou', 'wcfw_renderThankYou', 10);
add_action('woocommerce_after_cart_contents', 'wcfw_renderReviewOrder', 10);
add_action('woocommerce_shipping_init', 'wcfw_shippingMethodInit');
add_filter('woocommerce_shipping_methods', 'add_wcfw_shipping_method');

Argument 2 passed to App\Providers\AuthServiceProvider::App\Providers\{closure}() must be an instance of App\Post, string given,

Am getting the above error when i try to edit a blog post on my laravel 5.7 App. Any ideas on how to resolve this?
My Post Controller;
public function edit($id)
{
$post = Post::find($id);
return view('posts.edit')->withPost($post);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
// Form validation
$this->validate($request, array(
'title' =>'required|max:190',
'category' =>'required|max:190',
'body' =>'required'
));
//save in db
$post = Post::find($id);
$post->title=$request->input('title');
$post->category=$request->input('category');
$post->body=Purifier::clean($request->input('body'));
$post->save();
Session::flash('success','Blog successfuly updated!');
return redirect()->route('posts.show',$post->id);
}
My AuthServiceProvider;
public function registerPostPolicies()
{
Gate::define('create-post', function($user){
$user->hasAccess(['create-post']);
});
Gate::define('update-post', function($user, Post $post){
$user->hasAccess(['update-post']) or $user ->id ==$post -> user_id;
});
Gate::define('delete-post', function($user, Post $post){
$user->hasAccess(['delete-post']) or $user ->id ==$post -> user_id;
});
}
I have spent several hours trying to resolve the issue, but i dont seem to be making any progress.
Any help will be highly appreciated

Twilio - Laravel issue - Credentials are required to create a Client

I am receiving the following error
[2018-12-18 12:12:46] local.ERROR: Credentials are required to create a Client {"exception":"[object] (Twilio\Exceptions\ConfigurationException(code: 0): Credentials are required to create a Client at C:\wamp64\www\_javid\javid\vendor\twilio\sdk\Twilio\Rest\Client.php:157)
I will include the code below and the source i used to create it. I would like to add, this was all working correctly the other evening.
Today, i merely added a new function to handle the saving of messages to the database. Then i started receiving the above error. Naturally i reverted my changes but still the same error.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Auth;
use JWTAuth;
use App\Item;
use Log;
use Twilio\Rest\Client;
class MessagingController extends Controller
{
protected $client;
public function __construct(Client $client){
$this->client = $client;
}
/**
* Show the form for creating a notification.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('notifications.create');
}
public function sendMessage(request $request){
$details = $request->only('membershipNumber', 'countryCode', 'message');
$user = User::where('membership_number', $details['membershipNumber'])->with('mobile_number')->first();
if(count($user)>0){
$this->messageSaveToDatabase($details, $user);
$this->messageSendToMobile($details, $user);
$this->messageSendToEmail($details, $user);
return response([
'status' => 'success',
'msg' => __('messages.success'),
'response' => $details
], 200);
} else {
return response([
'status' => 'error',
'msg' => __('messages.error')
], 200);
}
}
protected function messageSaveToDatabase($details, $user){
}
protected function messageSendToMobile($details, $user, $imageUrl = null){
$lineBreak = "\n\n";
$phoneNumber = $user->mobile_number->country_code.decrypt($user->mobile_number->number);
$message = "Hi member #".$details['membershipNumber'].$lineBreak.
$details['message'];
$twilioPhoneNumber = config('services.twilio')['phoneNumber'];
$messageParams = array(
'from' => $twilioPhoneNumber,
'body' => $message
);
if ($imageUrl) {
$messageParams['mediaUrl'] = $imageUrl;
}
$this->client->messages->create(
$phoneNumber,
$messageParams
);
}
protected function messageSendToEmail($details, $user){
}
}
I have checked the TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN, these are both correct.
The code was taken from the following guide, i stripped out the subscriber part. Guide from Twilio
one more thing, I found the following Here which suggests i need to do something like this $client = new Client($keySid, $keySecret, $accountSid); but the guide above, does not do this, plus it all worked like this also.
Any help or suggestions would be great, i'm running out of hair to pull out :(
After a little more googling and some re-working, I found a working solution
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Auth;
use Twilio\Rest\Client;
class MessagingController extends Controller
{
protected function messageSendToMobile($details, $message, $user, $imageUrl = null){
$accountSid = env('TWILIO_ACCOUNT_SID');
$authToken = env('TWILIO_AUTH_TOKEN');
$twilioNumber = env('TWILIO_PHONE_NUMBER');
$lineBreak = "\n\n";
$to = $user->mobile_number->country_code.decrypt($user->mobile_number->number);
$client = new Client($accountSid, $authToken);
try {
$client->messages->create(
$to,
[
"body" => $message,
"from" => $twilioNumber
]
);
Log::info('Message sent to ' . $twilioNumber);
} catch (TwilioException $e) {
Log::error(
'Could not send SMS notification.' .
' Twilio replied with: ' . $e
);
}
}
}

how to send scheduled emails with sendGrid and symfony

I'm building an application with symfony3 in which I have an EmailService basin on SendGridService.
Sending emails is okay, but I want to schedule my emails.
This is SendGridEmailService :
<?php
namespace AppBundle\Services;
use SendGrid;
use Swift_Attachment;
use Swift_Mailer;
use Swift_Message;
use Swift_SmtpTransport;
use Twig_Environment;
class SendGirdEmailService
{
/**
* Library to facilitate email messages being sent out, sendMail deprecated in symfony 1.2
*
* #param string $partial - Array with html and text partials ie array('text'=>'textPartial', 'html'=>'htmlPartial')
* #param array $parameters - Array we will pass into the partials
* #param string $mailFrom - Email source
* #param string $mailTo - Email destination
* #param string $subject - The subject of the email message
* #param array $sgHeaders - What we will be placing in the SMTPAPI header. Must be null or a non-empty array
* #param array $attachments - Email contains the attachments
*/
public static function sendEmail($partials, $parameters, $mailFrom, $mailTo, $subject, $sgHeaders = null, $attachments = null)
{
// verify we have username/password to send out emails - IMPORTANT
/* if (!sfconfig::has('app_sendgrid_username') or !sfconfig::has('app_sendgrid_password')) {
throw new sfException('SMTP username/password is required to send email out');
}*/
$text = null;
$html = null;
if (is_array($partials)) {
// load libraries
//sfContext::getInstance()->getConfiguration()->loadHelpers('Partial');
if (isset($partials['text'])) {
$text = $partials['text'];
}
if (isset($partials['html'])) {
$html = $partials['html'];
}
}
if ($text === null and $html === null) {
throw new sfException('A text and/or HTML partial must be given');
}
try {
/*
* Load connection for mailer
*/
$connection = Swift_SmtpTransport::newInstance('smtp.sendgrid.net', 465, 'ssl')->setUsername('xxxxxx')->setPassword('xxxxxxx');
// setup connection/content
$mailer = Swift_Mailer::newInstance($connection);
$message = Swift_Message::newInstance()->setSubject($subject)->setTo($mailTo);
if ($text and $html) {
$message->setBody($html, 'text/html');
$message->addPart($text, 'text/plain');
} else if ($text) {
$message->setBody($text, 'text/plain');
} else {
$message->setBody($html, 'text/html');
}
// if contains SMTPAPI header add it
if (null !== $sgHeaders) {
$message->getHeaders()->addTextHeader('X-SMTPAPI', json_encode($sgHeaders));
}
// update the from address line to include an actual name
if (is_array($mailFrom) and count($mailFrom) == 2) {
$mailFrom = array(
$mailFrom['email'] => $mailFrom['name']
);
}
// add attachments to email
if ($attachments !== null and is_array($attachments)) {
foreach ($attachments as $attachment) {
$attach = Swift_Attachment::fromPath($attachment['file'], $attachment['mime'])->setFilename($attachment['filename']);
$message->attach($attach);
}
}
// Send
$message->setFrom($mailFrom);
$mailer->send($message);
}
catch (Exception $e) {
throw new sfException('Error sending email out - ' . $e->getMessage());
}
}
}
And this is the function I'm using to send my emails:
SendGirdEmailService::sendEmail(array(
'text' => $htmlContent,
'html' => $htmlContent
),
null,
$this->from,
$to,
$subject,
$sgHeaders = null,
$attachments = null
);
How can I set the parameters to send emails after one hour for example?
I found solution by setting an array with 'sent_at' index with timestamp value like :
SendGirdEmailService::sendEmail(array(
'text' => $htmlContent,
'html' => $htmlContent,
),
null,
$this->from,
$to,
$subject,
$sgHeaders =
array('send_at' => strtotime('+1 day', date_timestamp_get(new \DateTime()) ) ),
$attachments = null
);

Call symfony console command with sudo from Controller

I'm implementing a web interface using symfony which allow some system restricted command.
To better separate the logic of my code, I've create some console command like:
app/console system:do-restricted --option
And then I call the command from controller like this:
$status = $console->run(new ArrayInput([
'command' => 'system:do-restricted',
'--option' => true
]), $output = new BufferedOutput());
Is there a way to allow sudo of the console command?
I think the only way is to reconvert the above command to the shell form and use Process, in which case, there is a simple way to convert InputArray to command and stdout to OutputBaffer (+ansi colors)?
In the end, I've implemented this class to be used in place of symfony's Console\Application:
<?php
namespace Acme\Model;
use Symfony\Component\Process\Process;
use Symfony\Component\Console\Input\ArrayInput;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Symfony\Component\Console\Output\OutputInterface;
final class Console implements LoggerAwareInterface
{
use LoggerAwareTrait;
private $consoleCommand;
public function __construct($consoleCommand = 'sudo app/console')
{
$this->consoleCommand = $consoleCommand;
}
/**
* Create a process for console command.
*
* #param string $command
* #param array[] $argv Same syntax as symfony ArrayInput
*
* #see Symfony\Component\Console\Input\ArrayInput
*/
public function process($command, array $argv = [])
{
$console = escapeshellcmd($this->consoleCommand);
$command = escapeshellarg($command);
$options = [];
$arguments = [];
foreach ($argv as $name => $value) {
if ('--' === substr($name, 0, 2)) {
if (false === $value) {
continue;
}
$option = $name;
if (is_string($value)) {
$option .= '='.$value;
}
$options[] = escapeshellarg($option);
} else {
$arguments[] = escapeshellarg($value);
}
}
$process = new Process(
$console.' '
.$command.' '
.implode(' ', $options).' '
.implode(' ', $arguments)
);
if ($this->logger) {
$this->logger->info(sprintf('Created process for command: %s', $process->getCommandLine()));
}
return $process;
}
/**
* Run a console command.
*
* #param string $command One of the 'app/console' commands
* #param array[] $argv Assoc array '--opt' => true/false, '--opt' => 'value' or 'arg_name' => 'arg_value'
* #param OutputInterface|null $output Output object
*
* #see Symfony\Component\Console\Input\ArrayInput
*/
public function run($command, array $argv = [], OutputInterface $output = null)
{
if ($output->isDecorated()) {
$argv['--ansi'] = true;
}
$process = $this->process($command, $argv);
$callable = null;
if (null !== $output) {
$callable = function ($type, $line) use ($output) {
$output->writeln($line);
};
}
$exitCode = $process->run($callable);
if ($this->logger) {
$this->logger->info(sprintf('Command returned: %d', $exitCode), ['output' => $output]);
}
return $exitCode;
}
}
And then I call it like this:
$status = $this->console->run(
'balancer:cluster:copy-config',
['--option' => true, '--opt-val' => 'value', 'arg1' => 'value1'],
$output = new BufferedOutput()
);

Resources