1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 05:02:36 +01:00

Remove action header again

This commit is contained in:
rafael.sisweb 2015-11-30 06:29:43 -05:00
commit c182b67408
80 changed files with 2247 additions and 1633 deletions

View File

@ -6,6 +6,7 @@ APP_KEY=SomeRandomString
APP_TIMEZONE
DB_TYPE=mysql
DB_STRICT=false
DB_HOST=localhost
DB_DATABASE=ninja
DB_USERNAME
@ -22,6 +23,7 @@ MAIL_PASSWORD
PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'
LOG=single
REQUIRE_HTTPS=false
GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET

View File

@ -51,26 +51,21 @@ class AccountApiController extends BaseAPIController
$this->accountRepo->createTokens($user, $request->token_name);
$users = $this->accountRepo->findUsers($user, 'account.account_tokens');
$data = $this->createCollection($users, new UserAccountTransformer($user->account, $request->token_name));
$transformer = new UserAccountTransformer($user->account, $request->serializer, $request->token_name);
$data = $this->createCollection($users, $transformer, 'user_account');
$response = [
'user_accounts' => $data
];
return $this->response($response);
return $this->response($data);
}
public function show()
public function show(Request $request)
{
$account = Auth::user()->account;
$account->loadAllData();
$account = $this->createItem($account, new AccountTransformer);
$response = [
'account' => $account
];
$transformer = new AccountTransformer(null, $request->serializer);
$account = $this->createItem($account, $transformer, 'account');
return $this->response($response);
return $this->response($account);
}
public function getStaticData()

View File

@ -212,13 +212,8 @@ class AccountController extends BaseController
{
// check that logo is less than the max file size
$account = Auth::user()->account;
if ($account->hasLogo()) {
$filename = $account->getLogoPath();
$bytes = File::size($filename);
if ($bytes > MAX_LOGO_FILE_SIZE * 1000) {
$bytes /= 1000;
Session::flash('warning', trans('texts.logo_too_large', ['size' => round($bytes) . 'KB']));
}
if ($account->isLogoTooLarge()) {
Session::flash('warning', trans('texts.logo_too_large', ['size' => $account->getLogoSize() . 'KB']));
}
$data = [
@ -272,6 +267,12 @@ class AccountController extends BaseController
$account->load('account_gateways');
$count = count($account->account_gateways);
if ($accountGateway = $account->getGatewayConfig(GATEWAY_STRIPE)) {
if ( ! $accountGateway->getPublishableStripeKey()) {
Session::flash('warning', trans('texts.missing_publishable_key'));
}
}
if ($count == 0) {
return Redirect::to('gateways/create');
} else {

View File

@ -236,6 +236,13 @@ class AccountGatewayController extends BaseController
}
}
$publishableKey = Input::get('publishable_key');
if ($publishableKey = str_replace('*', '', $publishableKey)) {
$config->publishableKey = $publishableKey;
} elseif ($oldConfig && property_exists($oldConfig, 'publishableKey')) {
$config->publishableKey = $oldConfig->publishableKey;
}
$cardCount = 0;
if ($creditcards) {
foreach ($creditcards as $card => $value) {

View File

@ -1,12 +1,16 @@
<?php namespace App\Http\Controllers;
use Session;
use Utils;
use Response;
use Request;
use League\Fractal;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Collection;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use App\Ninja\Serializers\ArraySerializer;
use League\Fractal\Serializer\JsonApiSerializer;
/**
* @SWG\Swagger(
@ -41,31 +45,88 @@ use App\Ninja\Serializers\ArraySerializer;
class BaseAPIController extends Controller
{
protected $manager;
protected $serializer;
public function __construct()
{
$this->manager = new Manager();
$this->manager->setSerializer(new ArraySerializer());
if ($include = Request::get('include')) {
$this->manager->parseIncludes($include);
}
$this->serializer = Request::get('serializer') ?: API_SERIALIZER_ARRAY;
if ($this->serializer === API_SERIALIZER_JSON) {
$this->manager->setSerializer(new JsonApiSerializer());
} else {
$this->manager->setSerializer(new ArraySerializer());
}
}
protected function createItem($data, $transformer)
protected function createItem($data, $transformer, $entityType)
{
$resource = new Item($data, $transformer);
if ($this->serializer && $this->serializer != API_SERIALIZER_JSON) {
$entityType = null;
}
$resource = new Item($data, $transformer, $entityType);
return $this->manager->createData($resource)->toArray();
}
protected function createCollection($data, $transformer)
protected function createCollection($data, $transformer, $entityType, $paginator = false)
{
$resource = new Collection($data, $transformer);
if ($this->serializer && $this->serializer != API_SERIALIZER_JSON) {
$entityType = null;
}
$resource = new Collection($data, $transformer, $entityType);
if ($paginator) {
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
}
return $this->manager->createData($resource)->toArray();
}
protected function response($response)
{
$index = Request::get('index') ?: 'data';
$meta = isset($response['meta']) ? $response['meta'] : null;
$response = [
$index => $response
];
if ($meta) {
$response['meta'] = $meta;
unset($response[$index]['meta']);
}
$response = json_encode($response, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
return Response::make($response, 200, $headers);
}
protected function getIncluded()
{
$data = ['user'];
$included = Request::get('include');
$included = explode(',', $included);
foreach ($included as $include) {
if ($include == 'invoices') {
$data[] = 'invoices.invoice_items';
$data[] = 'invoices.user';
} elseif ($include == 'clients') {
$data[] = 'clients.contacts';
$data[] = 'clients.user';
} elseif ($include) {
$data[] = $include;
}
}
return $data;
}
}

View File

@ -3,16 +3,21 @@
use Utils;
use Response;
use Input;
use Auth;
use App\Models\Client;
use App\Ninja\Repositories\ClientRepository;
use App\Http\Requests\CreateClientRequest;
use App\Http\Controllers\BaseAPIController;
use App\Ninja\Transformers\ClientTransformer;
class ClientApiController extends Controller
class ClientApiController extends BaseAPIController
{
protected $clientRepo;
public function __construct(ClientRepository $clientRepo)
{
parent::__construct();
$this->clientRepo = $clientRepo;
}
@ -42,15 +47,16 @@ class ClientApiController extends Controller
public function index()
{
$clients = Client::scope()
->with('country', 'contacts', 'industry', 'size', 'currency')
->with($this->getIncluded())
->orderBy('created_at', 'desc')
->get();
$clients = Utils::remapPublicIds($clients);
->paginate();
$response = json_encode($clients, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($clients));
$transformer = new ClientTransformer(Auth::user()->account, Input::get('serializer'));
$paginator = Client::scope()->paginate();
return Response::make($response, 200, $headers);
$data = $this->createCollection($clients, $transformer, ENTITY_CLIENT, $paginator);
return $this->response($data);
}
/**
@ -77,12 +83,14 @@ class ClientApiController extends Controller
public function store(CreateClientRequest $request)
{
$client = $this->clientRepo->save($request->input());
$client = Client::scope($client->public_id)
->with('country', 'contacts', 'industry', 'size', 'currency')
->first();
$client = Client::scope($client->public_id)->with('country', 'contacts', 'industry', 'size', 'currency')->first();
$client = Utils::remapPublicIds([$client]);
$response = json_encode($client, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
$transformer = new ClientTransformer(Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($client, $transformer, ENTITY_CLIENT);
return Response::make($response, 200, $headers);
return $this->response($data);
}
}

View File

@ -60,7 +60,7 @@ class ClientController extends BaseController
'date_created',
'last_login',
'balance',
'action'
''
]),
));
}

View File

@ -44,7 +44,7 @@ class CreditController extends BaseController
'credit_balance',
'credit_date',
'private_notes',
'action'
''
]),
));
}

View File

@ -21,41 +21,56 @@ class ImportController extends BaseController
public function doImport()
{
$source = Input::get('source');
$files = [];
$skipped = [];
if ($source === IMPORT_CSV) {
$filename = Input::file('client_file')->getRealPath();
$data = $this->importService->mapFile($filename);
foreach (ImportService::$entityTypes as $entityType) {
if (Input::file("{$entityType}_file")) {
$files[$entityType] = Input::file("{$entityType}_file")->getRealPath();
}
}
return View::make('accounts.import_map', $data);
} else {
$files = [];
foreach (ImportService::$entityTypes as $entityType) {
if (Input::file("{$entityType}_file")) {
$files[$entityType] = Input::file("{$entityType}_file")->getRealPath();
try {
if ($source === IMPORT_CSV) {
$data = $this->importService->mapCSV($files);
return View::make('accounts.import_map', ['data' => $data]);
} else {
$skipped = $this->importService->import($source, $files);
if (count($skipped)) {
$message = trans('texts.failed_to_import');
foreach ($skipped as $skip) {
$message .= '<br/>' . json_encode($skip);
}
Session::flash('warning', $message);
} else {
Session::flash('message', trans('texts.imported_file'));
}
}
try {
$result = $this->importService->import($source, $files);
Session::flash('message', trans('texts.imported_file') . ' - ' . $result);
} catch (Exception $exception) {
Session::flash('error', $exception->getMessage());
}
return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
} catch (Exception $exception) {
Session::flash('error', $exception->getMessage());
}
return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
}
public function doImportCSV()
{
$map = Input::get('map');
$hasHeaders = Input::get('header_checkbox');
$headers = Input::get('headers');
$skipped = [];
try {
$count = $this->importService->importCSV($map, $hasHeaders);
$message = Utils::pluralize('created_client', $count);
$skipped = $this->importService->importCSV($map, $headers);
Session::flash('message', $message);
if (count($skipped)) {
$message = trans('texts.failed_to_import');
foreach ($skipped as $skip) {
$message .= '<br/>' . json_encode($skip);
}
Session::flash('warning', $message);
} else {
Session::flash('message', trans('texts.imported_file'));
}
} catch (Exception $exception) {
Session::flash('error', $exception->getMessage());
}

View File

@ -13,13 +13,17 @@ use App\Models\Invitation;
use App\Ninja\Repositories\ClientRepository;
use App\Ninja\Repositories\InvoiceRepository;
use App\Ninja\Mailers\ContactMailer as Mailer;
use App\Http\Controllers\BaseAPIController;
use App\Ninja\Transformers\InvoiceTransformer;
class InvoiceApiController extends Controller
class InvoiceApiController extends BaseAPIController
{
protected $invoiceRepo;
public function __construct(InvoiceRepository $invoiceRepo, ClientRepository $clientRepo, Mailer $mailer)
{
parent::__construct();
$this->invoiceRepo = $invoiceRepo;
$this->clientRepo = $clientRepo;
$this->mailer = $mailer;
@ -41,20 +45,24 @@ class InvoiceApiController extends Controller
* )
* )
*/
public function index($clientPublicId = false)
public function index()
{
$paginator = Invoice::scope();
$invoices = Invoice::scope()
->with('client', 'invitations.account')
->with(array_merge(['invoice_items'], $this->getIncluded()))
->where('invoices.is_quote', '=', false);
if ($clientPublicId) {
$invoices->whereHas('client', function($query) use ($clientPublicId) {
if ($clientPublicId = Input::get('client_id')) {
$filter = function($query) use ($clientPublicId) {
$query->where('public_id', '=', $clientPublicId);
});
};
$invoices->whereHas('client', $filter);
$paginator->whereHas('client', $filter);
}
$invoices = $invoices->orderBy('created_at', 'desc')->get();
$invoices = $invoices->orderBy('created_at', 'desc')->paginate();
/*
// Add the first invitation link to the data
foreach ($invoices as $key => $invoice) {
foreach ($invoice->invitations as $subKey => $invitation) {
@ -62,13 +70,14 @@ class InvoiceApiController extends Controller
}
unset($invoice['invitations']);
}
*/
$invoices = Utils::remapPublicIds($invoices);
$response = json_encode($invoices, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($invoices));
$transformer = new InvoiceTransformer(Auth::user()->account, Input::get('serializer'));
$paginator = $paginator->paginate();
return Response::make($response, 200, $headers);
$data = $this->createCollection($invoices, $transformer, 'invoices', $paginator);
return $this->response($data);
}
@ -145,14 +154,14 @@ class InvoiceApiController extends Controller
if (!$error) {
if (!isset($data['client_id']) && !isset($data['email'])) {
$error = trans('validation.', ['attribute' => 'client_id or email']);
$error = trans('validation.required_without', ['attribute' => 'client_id', 'values' => 'email']);
} else if (!$client) {
$error = trans('validation.not_in', ['attribute' => 'client_id']);
}
}
if ($error) {
$response = json_encode($error, JSON_PRETTY_PRINT);
return $error;
} else {
$data = self::prepareData($data, $client);
$data['client_id'] = $client->id;
@ -170,16 +179,12 @@ class InvoiceApiController extends Controller
$this->mailer->sendInvoice($invoice);
}
// prepare the return data
$invoice = Invoice::scope($invoice->public_id)->with('client', 'invoice_items', 'invitations')->first();
$invoice = Utils::remapPublicIds([$invoice]);
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
$response = json_encode($invoice, JSON_PRETTY_PRINT);
return $this->response($data);
}
$headers = Utils::getApiHeaders();
return Response::make($response, $error ? 400 : 200, $headers);
}
private function prepareData($data, $client)

View File

@ -69,7 +69,7 @@ class InvoiceController extends BaseController
'balance_due',
'due_date',
'status',
'action'
''
]),
];
@ -326,7 +326,7 @@ class InvoiceController extends BaseController
if ($clientPublicId) {
$clientId = Client::getPrivateId($clientPublicId);
}
$invoice = $account->createInvoice($entityType, $clientId);
$invoice->public_id = 0;

View File

@ -1,18 +1,23 @@
<?php namespace App\Http\Controllers;
use Auth;
use Input;
use Utils;
use Response;
use App\Models\Payment;
use App\Models\Invoice;
use App\Ninja\Repositories\PaymentRepository;
use App\Http\Controllers\BaseAPIController;
use App\Ninja\Transformers\PaymentTransformer;
class PaymentApiController extends Controller
class PaymentApiController extends BaseAPIController
{
protected $paymentRepo;
public function __construct(PaymentRepository $paymentRepo)
{
parent::__construct();
$this->paymentRepo = $paymentRepo;
}
@ -32,27 +37,29 @@ class PaymentApiController extends Controller
* )
* )
*/
public function index($clientPublicId = false)
public function index()
{
$paginator = Payment::scope();
$payments = Payment::scope()
->with('client', 'contact', 'invitation', 'user', 'invoice');
->with('client.contacts', 'invitation', 'user', 'invoice');
if ($clientPublicId) {
$payments->whereHas('client', function($query) use ($clientPublicId) {
if ($clientPublicId = Input::get('client_id')) {
$filter = function($query) use ($clientPublicId) {
$query->where('public_id', '=', $clientPublicId);
});
};
$payments->whereHas('client', $filter);
$paginator->whereHas('client', $filter);
}
$payments = $payments->orderBy('created_at', 'desc')->get();
$payments = Utils::remapPublicIds($payments);
$payments = $payments->orderBy('created_at', 'desc')->paginate();
$paginator = $paginator->paginate();
$transformer = new PaymentTransformer(Auth::user()->account, Input::get('serializer'));
$response = json_encode($payments, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($payments));
$data = $this->createCollection($payments, $transformer, 'payments', $paginator);
return Response::make($response, 200, $headers);
return $this->response($data);
}
/**
* @SWG\Post(
* path="/payments",
@ -96,15 +103,17 @@ class PaymentApiController extends Controller
$data['transaction_reference'] = '';
}
if (!$error) {
$payment = $this->paymentRepo->save($data);
$payment = Payment::scope($payment->public_id)->with('client', 'contact', 'user', 'invoice')->first();
$payment = Utils::remapPublicIds([$payment]);
if ($error) {
return $error;
}
$response = json_encode($error ?: $payment, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
return Response::make($response, 200, $headers);
$payment = $this->paymentRepo->save($data);
$payment = Payment::scope($payment->public_id)->with('client', 'contact', 'user', 'invoice')->first();
$transformer = new PaymentTransformer(Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($payment, $transformer, 'payment');
return $this->response($data);
}
}

View File

@ -54,7 +54,7 @@ class PaymentController extends BaseController
'method',
'payment_amount',
'payment_date',
'action'
''
]),
));
}
@ -168,6 +168,7 @@ class PaymentController extends BaseController
'client' => $client,
'contact' => $invitation->contact,
'gateway' => $gateway,
'accountGateway' => $accountGateway,
'acceptedCreditCardTypes' => $acceptedCreditCardTypes,
'countries' => Cache::get('countries'),
'currencyId' => $client->getCurrencyId(),
@ -349,12 +350,20 @@ class PaymentController extends BaseController
$rules = [
'first_name' => 'required',
'last_name' => 'required',
'card_number' => 'required',
'expiration_month' => 'required',
'expiration_year' => 'required',
'cvv' => 'required',
];
if ( ! Input::get('stripeToken')) {
$rules = array_merge(
$rules,
[
'card_number' => 'required',
'expiration_month' => 'required',
'expiration_year' => 'required',
'cvv' => 'required',
]
);
}
if ($accountGateway->show_address) {
$rules = array_merge($rules, [
'address1' => 'required',
@ -399,12 +408,17 @@ class PaymentController extends BaseController
// check if we're creating/using a billing token
if ($accountGateway->gateway_id == GATEWAY_STRIPE) {
if ($token = Input::get('stripeToken')) {
$details['token'] = $token;
unset($details['card']);
}
if ($useToken) {
$details['cardReference'] = $client->getGatewayToken();
$details['customerReference'] = $client->getGatewayToken();
} elseif ($account->token_billing_type_id == TOKEN_BILLING_ALWAYS || Input::get('token_billing')) {
$token = $this->paymentService->createToken($gateway, $details, $accountGateway, $client, $invitation->contact_id);
if ($token) {
$details['cardReference'] = $token;
$details['customerReference'] = $token;
} else {
$this->error('Token-No-Ref', $this->paymentService->lastError, $accountGateway);
return Redirect::to('payment/'.$invitationKey)->withInput();

View File

@ -1,16 +1,22 @@
<?php namespace App\Http\Controllers;
use Auth;
use Input;
use Utils;
use Response;
use App\Models\Invoice;
use App\Ninja\Repositories\InvoiceRepository;
use App\Http\Controllers\BaseAPIController;
use App\Ninja\Transformers\QuoteTransformer;
class QuoteApiController extends Controller
class QuoteApiController extends BaseAPIController
{
protected $invoiceRepo;
public function __construct(InvoiceRepository $invoiceRepo)
{
parent::__construct();
$this->invoiceRepo = $invoiceRepo;
}
@ -30,25 +36,29 @@ class QuoteApiController extends Controller
* )
* )
*/
public function index($clientPublicId = false)
public function index()
{
$paginator = Invoice::scope();
$invoices = Invoice::scope()
->with('client', 'user')
->with('client', 'invitations', 'user', 'invoice_items')
->where('invoices.is_quote', '=', true);
if ($clientPublicId) {
$invoices->whereHas('client', function($query) use ($clientPublicId) {
if ($clientPublicId = Input::get('client_id')) {
$filter = function($query) use ($clientPublicId) {
$query->where('public_id', '=', $clientPublicId);
});
};
$invoices->whereHas('client', $filter);
$paginator->whereHas('client', $filter);
}
$invoices = $invoices->orderBy('created_at', 'desc')->get();
$invoices = Utils::remapPublicIds($invoices);
$invoices = $invoices->orderBy('created_at', 'desc')->paginate();
$transformer = new QuoteTransformer(\Auth::user()->account, Input::get('serializer'));
$paginator = $paginator->paginate();
$response = json_encode($invoices, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($invoices));
$data = $this->createCollection($invoices, $transformer, 'quotes', $paginator);
return Response::make($response, 200, $headers);
return $this->response($data);
}
/*

View File

@ -1,17 +1,22 @@
<?php namespace App\Http\Controllers;
use Auth;
use Utils;
use Response;
use Input;
use App\Models\Task;
use App\Ninja\Repositories\TaskRepository;
use App\Http\Controllers\BaseAPIController;
use App\Ninja\Transformers\TaskTransformer;
class TaskApiController extends Controller
class TaskApiController extends BaseAPIController
{
protected $taskRepo;
public function __construct(TaskRepository $taskRepo)
{
parent::__construct();
$this->taskRepo = $taskRepo;
}
@ -31,23 +36,27 @@ class TaskApiController extends Controller
* )
* )
*/
public function index($clientPublicId = false)
public function index()
{
$tasks = Task::scope()->with('client');
$paginator = Task::scope();
$tasks = Task::scope()
->with($this->getIncluded());
if ($clientPublicId) {
$tasks->whereHas('client', function($query) use ($clientPublicId) {
if ($clientPublicId = Input::get('client_id')) {
$filter = function($query) use ($clientPublicId) {
$query->where('public_id', '=', $clientPublicId);
});
};
$tasks->whereHas('client', $filter);
$paginator->whereHas('client', $filter);
}
$tasks = $tasks->orderBy('created_at', 'desc')->get();
$tasks = Utils::remapPublicIds($tasks);
$tasks = $tasks->orderBy('created_at', 'desc')->paginate();
$paginator = $paginator->paginate();
$transformer = new TaskTransformer(\Auth::user()->account, Input::get('serializer'));
$response = json_encode($tasks, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($tasks));
$data = $this->createCollection($tasks, $transformer, 'tasks', $paginator);
return Response::make($response, 200, $headers);
return $this->response($data);
}
/**
@ -82,12 +91,11 @@ class TaskApiController extends Controller
$task = $this->taskRepo->save($taskId, $data);
$task = Task::scope($task->public_id)->with('client')->first();
$task = Utils::remapPublicIds([$task]);
$response = json_encode($task, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
$transformer = new TaskTransformer(Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($task, $transformer, 'task');
return Response::make($response, 200, $headers);
return $this->response($data);
}
}

View File

@ -50,7 +50,7 @@ class TaskController extends BaseController
'duration',
'description',
'status',
'action'
''
]),
));
}

View File

@ -33,7 +33,7 @@ class StartupCheck
}
// Ensure all request are over HTTPS in production
if (Utils::isNinjaProd() && !Request::secure()) {
if (Utils::requireHTTPS() && !Request::secure()) {
return Redirect::secure(Request::getRequestUri());
}

View File

@ -199,13 +199,13 @@ Route::group(['middleware' => 'api', 'prefix' => 'api/v1'], function()
Route::get('static', 'AccountApiController@getStaticData');
Route::get('accounts', 'AccountApiController@show');
Route::resource('clients', 'ClientApiController');
Route::get('quotes/{client_id?}', 'QuoteApiController@index');
Route::get('quotes', 'QuoteApiController@index');
Route::resource('quotes', 'QuoteApiController');
Route::get('invoices/{client_id?}', 'InvoiceApiController@index');
Route::get('invoices', 'InvoiceApiController@index');
Route::resource('invoices', 'InvoiceApiController');
Route::get('payments/{client_id?}', 'PaymentApiController@index');
Route::get('payments', 'PaymentApiController@index');
Route::resource('payments', 'PaymentApiController');
Route::get('tasks/{client_id?}', 'TaskApiController@index');
Route::get('tasks', 'TaskApiController@index');
Route::resource('tasks', 'TaskApiController');
Route::post('hooks', 'IntegrationController@subscribe');
Route::post('email_invoice', 'InvoiceApiController@emailInvoice');
@ -250,7 +250,9 @@ if (!defined('CONTACT_EMAIL')) {
define('RECENTLY_VIEWED', 'RECENTLY_VIEWED');
define('ENTITY_CLIENT', 'client');
define('ENTITY_CONTACT', 'contact');
define('ENTITY_INVOICE', 'invoice');
define('ENTITY_INVOICE_ITEMS', 'invoice_items');
define('ENTITY_RECURRING_INVOICE', 'recurring_invoice');
define('ENTITY_PAYMENT', 'payment');
define('ENTITY_CREDIT', 'credit');
@ -433,7 +435,7 @@ if (!defined('CONTACT_EMAIL')) {
define('NINJA_GATEWAY_CONFIG', 'NINJA_GATEWAY_CONFIG');
define('NINJA_WEB_URL', 'https://www.invoiceninja.com');
define('NINJA_APP_URL', 'https://app.invoiceninja.com');
define('NINJA_VERSION', '2.4.6');
define('NINJA_VERSION', '2.4.7');
define('NINJA_DATE', '2000-01-01');
define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com');
@ -441,7 +443,7 @@ if (!defined('CONTACT_EMAIL')) {
define('ZAPIER_URL', 'https://zapier.com/zapbook/invoice-ninja');
define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/');
define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html');
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/single/browser/v1/');
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/api/browser/v2/');
define('PHP_DATE_FORMATS', 'http://php.net/manual/en/function.date.php');
define('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/referral-program/');
@ -492,7 +494,9 @@ if (!defined('CONTACT_EMAIL')) {
define('USER_STATE_PENDING', 'pending');
define('USER_STATE_DISABLED', 'disabled');
define('USER_STATE_ADMIN', 'admin');
define('API_SERIALIZER_ARRAY', 'array');
define('API_SERIALIZER_JSON', 'json');
$creditCards = [
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
@ -542,8 +546,8 @@ if (!defined('CONTACT_EMAIL')) {
}
}
/*
// Log all SQL queries to laravel.log
/*
if (Utils::isNinjaDev()) {
Event::listen('illuminate.query', function($query, $bindings, $time, $name) {
$data = compact('bindings', 'time', 'name');

View File

@ -60,6 +60,11 @@ class Utils
return isset($_ENV['NINJA_DEV']) && $_ENV['NINJA_DEV'] == 'true';
}
public static function requireHTTPS()
{
return Utils::isNinjaProd() || (isset($_ENV['REQUIRE_HTTPS']) && $_ENV['REQUIRE_HTTPS'] == 'true');
}
public static function isOAuthEnabled()
{
$providers = [
@ -227,6 +232,13 @@ class Utils
return floatval($value);
}
public static function parseInt($value)
{
$value = preg_replace('/[^0-9]/', '', $value);
return intval($value);
}
public static function formatMoney($value, $currencyId = false, $showSymbol = true)
{
if (!$currencyId) {
@ -585,18 +597,6 @@ class Utils
}
}
public static function remapPublicIds($items)
{
$return = [];
foreach ($items as $item) {
$return[] = $item->toPublicArray();
}
return $return;
}
public static function hideIds($data, $mapped = false)
{
$publicId = null;

View File

@ -45,6 +45,14 @@ class HandleUserLoggedIn {
Session::put(SESSION_USER_ACCOUNTS, $users);
$account->loadLocalizationSettings();
// if they're using Stripe make sure they're using Stripe.js
$accountGateway = $account->getGatewayConfig(GATEWAY_STRIPE);
if ($accountGateway && ! $accountGateway->getPublishableStripeKey()) {
Session::flash('warning', trans('texts.missing_publishable_key'));
} elseif ($account->isLogoTooLarge()) {
Session::flash('warning', trans('texts.logo_too_large', ['size' => $account->getLogoSize() . 'KB']));
}
}
}

View File

@ -6,6 +6,7 @@ use Session;
use DateTime;
use Event;
use App;
use File;
use App\Events\UserSettingsChanged;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laracasts\Presenter\PresentableTrait;
@ -304,11 +305,13 @@ class Account extends Eloquent
{
$invoice = Invoice::createNew();
$invoice->is_recurring = false;
$invoice->is_quote = false;
$invoice->invoice_date = Utils::today();
$invoice->start_date = Utils::today();
$invoice->invoice_design_id = $this->invoice_design_id;
$invoice->client_id = $clientId;
if ($entityType === ENTITY_RECURRING_INVOICE) {
$invoice->invoice_number = microtime(true);
$invoice->is_recurring = true;
@ -441,7 +444,14 @@ class Account extends Eloquent
if ($invoice->is_quote && !$this->share_counter) {
$this->quote_number_counter += 1;
} else {
$this->invoice_number_counter += 1;
$default = $this->invoice_number_counter;
$actual = Utils::parseInt($invoice->invoice_number);
if ( ! $this->isPro() && $default != $actual) {
$this->invoice_number_counter = $actual + 1;
} else {
$this->invoice_number_counter += 1;
}
}
$this->save();
@ -572,6 +582,21 @@ class Account extends Eloquent
}
}
public function getLogoSize()
{
if (!$this->hasLogo()) {
return 0;
}
$filename = $this->getLogoPath();
return round(File::size($filename) / 1000);
}
public function isLogoTooLarge()
{
return $this->getLogoSize() > MAX_LOGO_FILE_SIZE;
}
public function getSubscription($eventId)
{
return Subscription::where('account_id', '=', $this->id)->where('event_id', '=', $eventId)->first();

View File

@ -57,5 +57,25 @@ class AccountGateway extends EntityModel
{
return json_decode(Crypt::decrypt($this->config));
}
public function getConfigField($field)
{
$config = $this->getConfig();
if (!$field || !property_exists($config, $field)) {
return false;
}
return $config->$field;
}
public function getPublishableStripeKey()
{
if ( ! $this->isGateway(GATEWAY_STRIPE)) {
return false;
}
return $this->getConfigField('publishableKey');
}
}

View File

@ -39,15 +39,52 @@ class Client extends EntityModel
'website',
];
public static $fieldName = 'Client - Name';
public static $fieldPhone = 'Client - Phone';
public static $fieldAddress1 = 'Client - Street';
public static $fieldAddress2 = 'Client - Apt/Floor';
public static $fieldCity = 'Client - City';
public static $fieldState = 'Client - State';
public static $fieldPostalCode = 'Client - Postal Code';
public static $fieldNotes = 'Client - Notes';
public static $fieldCountry = 'Client - Country';
public static $fieldName = 'name';
public static $fieldPhone = 'work_phone';
public static $fieldAddress1 = 'address1';
public static $fieldAddress2 = 'address2';
public static $fieldCity = 'city';
public static $fieldState = 'state';
public static $fieldPostalCode = 'postal_code';
public static $fieldNotes = 'notes';
public static $fieldCountry = 'country';
public static function getImportColumns()
{
return [
Client::$fieldName,
Client::$fieldPhone,
Client::$fieldAddress1,
Client::$fieldAddress2,
Client::$fieldCity,
Client::$fieldState,
Client::$fieldPostalCode,
Client::$fieldCountry,
Client::$fieldNotes,
Contact::$fieldFirstName,
Contact::$fieldLastName,
Contact::$fieldPhone,
Contact::$fieldEmail,
];
}
public static function getImportMap()
{
return [
'first' => 'first_name',
'last' => 'last_name',
'email' => 'email',
'mobile|phone' => 'phone',
'name|organization' => 'name',
'street2|address2' => 'address2',
'street|address|address1' => 'address1',
'city' => 'city',
'state|province' => 'state',
'zip|postal|code' => 'postal_code',
'country' => 'country',
'note' => 'notes',
];
}
public function account()
{

View File

@ -17,10 +17,10 @@ class Contact extends EntityModel
'send_invoice',
];
public static $fieldFirstName = 'Contact - First Name';
public static $fieldLastName = 'Contact - Last Name';
public static $fieldEmail = 'Contact - Email';
public static $fieldPhone = 'Contact - Phone';
public static $fieldFirstName = 'first_name';
public static $fieldLastName = 'last_name';
public static $fieldEmail = 'email';
public static $fieldPhone = 'phone';
public function account()
{

View File

@ -5,6 +5,7 @@ use DateTime;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laracasts\Presenter\PresentableTrait;
use App\Models\BalanceAffecting;
use App\Models\Client;
use App\Events\QuoteWasCreated;
use App\Events\QuoteWasUpdated;
use App\Events\InvoiceWasCreated;
@ -29,6 +30,7 @@ class Invoice extends EntityModel implements BalanceAffecting
'auto_bill' => 'boolean',
];
// used for custom invoice numbers
public static $patternFields = [
'counter',
'custom1',
@ -38,6 +40,40 @@ class Invoice extends EntityModel implements BalanceAffecting
'date:',
];
public static $fieldInvoiceNumber = 'invoice_number';
public static $fieldInvoiceDate = 'invoice_date';
public static $fieldDueDate = 'due_date';
public static $fieldAmount = 'amount';
public static $fieldPaid = 'paid';
public static $fieldNotes = 'notes';
public static $fieldTerms = 'terms';
public static function getImportColumns()
{
return [
Client::$fieldName,
Invoice::$fieldInvoiceNumber,
Invoice::$fieldInvoiceDate,
Invoice::$fieldDueDate,
Invoice::$fieldAmount,
Invoice::$fieldPaid,
Invoice::$fieldNotes,
Invoice::$fieldTerms,
];
}
public static function getImportMap()
{
return [
'number^po' => 'invoice_number',
'amount' => 'amount',
'organization' => 'name',
'paid^date' => 'paid',
'invoice_date|create_date' => 'invoice_date',
'terms' => 'terms',
'notes' => 'notes',
];
}
public function getRoute()
{
$entityType = $this->getEntityType();
@ -576,21 +612,28 @@ class Invoice extends EntityModel implements BalanceAffecting
$invitation = $this->invitations[0];
$link = $invitation->getLink();
$curl = curl_init();
$jsonEncodedData = json_encode([
'targetUrl' => "{$link}?phantomjs=true",
'requestType' => 'raw',
'delayTime' => 1000,
'url' => "{$link}?phantomjs=true",
'renderType' => 'html',
'outputAsJson' => false,
'renderSettings' => [
'passThroughHeaders' => true,
],
// 'delayTime' => 1000,
]);
$opts = [
CURLOPT_URL => PHANTOMJS_CLOUD . env('PHANTOMJS_CLOUD_KEY'),
CURLOPT_URL => PHANTOMJS_CLOUD . env('PHANTOMJS_CLOUD_KEY') . '/',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $jsonEncodedData,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Content-Length: '.strlen($jsonEncodedData)],
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: '.strlen($jsonEncodedData)
],
];
curl_setopt_array($curl, $opts);

View File

@ -0,0 +1,40 @@
<?php namespace App\Ninja\Import\CSV;
use League\Fractal\TransformerAbstract;
use App\Models\Country;
use League\Fractal\Resource\Item;
class ClientTransformer extends TransformerAbstract
{
public function transform($data, $maps)
{
if (isset($maps[ENTITY_CLIENT][$data->name])) {
return false;
}
if (isset($maps['countries'][$data->country])) {
$data->country_id = $maps['countries'][$data->country];
}
return new Item($data, function ($data) use ($maps) {
return [
'name' => isset($data->name) ? $data->name : null,
'work_phone' => isset($data->work_phone) ? $data->work_phone : null,
'address1' => isset($data->address1) ? $data->address1 : null,
'city' => isset($data->city) ? $data->city : null,
'state' => isset($data->state) ? $data->state : null,
'postal_code' => isset($data->postal_code) ? $data->postal_code : null,
'private_notes' => isset($data->notes) ? $data->notes : null,
'contacts' => [
[
'first_name' => isset($data->first_name) ? $data->first_name : null,
'last_name' => isset($data->last_name) ? $data->last_name : null,
'email' => isset($data->email) ? $data->email : null,
'phone' => isset($data->phone) ? $data->phone : null,
],
],
'country_id' => isset($data->country_id) ? $data->country_id : null,
];
});
}
}

View File

@ -0,0 +1,40 @@
<?php namespace App\Ninja\Import\CSV;
use League\Fractal\TransformerAbstract;
use League\Fractal\Resource\Item;
use App\Models\Client;
class InvoiceTransformer extends TransformerAbstract
{
public function transform($data, $maps)
{
if (isset($maps[ENTITY_INVOICE][$data->invoice_number])) {
return false;
}
if (isset($maps[ENTITY_CLIENT][$data->name])) {
$data->client_id = $maps[ENTITY_CLIENT][$data->name];
} else {
return false;
}
return new Item($data, function ($data) use ($maps) {
return [
'invoice_number' => isset($data->invoice_number) ? $data->invoice_number : null,
'paid' => isset($data->paid) ? (float) $data->paid : null,
'client_id' => (int) $data->client_id,
'po_number' => isset($data->po_number) ? $data->po_number : null,
'terms' => isset($data->terms) ? $data->terms : null,
'public_notes' => isset($data->notes) ? $data->notes : null,
'invoice_date_sql' => isset($data->invoice_date) ? $data->invoice_date : null,
'invoice_items' => [
[
'notes' => isset($data->notes) ? $data->notes : null,
'cost' => isset($data->amount) ? (float) $data->amount : null,
'qty' => 1,
]
],
];
});
}
}

View File

@ -0,0 +1,19 @@
<?php namespace App\Ninja\Import\CSV;
use League\Fractal\TransformerAbstract;
use League\Fractal\Resource\Item;
class PaymentTransformer extends TransformerAbstract
{
public function transform($data, $maps)
{
return new Item($data, function ($data) use ($maps) {
return [
'amount' => $data->paid,
'payment_date_sql' => isset($data->invoice_date) ? $data->invoice_date : null,
'client_id' => $data->client_id,
'invoice_id' => $data->invoice_id,
];
});
}
}

View File

@ -19,6 +19,7 @@ class CreditRepository extends BaseRepository
->join('contacts', 'contacts.client_id', '=', 'clients.id')
->where('clients.account_id', '=', \Auth::user()->account_id)
->where('clients.deleted_at', '=', null)
->where('contacts.deleted_at', '=', null)
->where('contacts.is_primary', '=', true)
->select('credits.public_id', 'clients.name as client_name', 'clients.public_id as client_public_id', 'credits.amount', 'credits.balance', 'credits.credit_date', 'clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'credits.private_notes', 'credits.deleted_at', 'credits.is_deleted');

View File

@ -138,13 +138,13 @@ class InvoiceRepository extends BaseRepository
if ($isNew) {
$entityType = ENTITY_INVOICE;
if (isset($data['is_recurring']) && $data['is_recurring']) {
if (isset($data['is_recurring']) && filter_var($data['is_recurring'], FILTER_VALIDATE_BOOLEAN)) {
$entityType = ENTITY_RECURRING_INVOICE;
} elseif (isset($data['is_quote']) && $data['is_quote']) {
} elseif (isset($data['is_quote']) && filter_var($data['is_quote'], FILTER_VALIDATE_BOOLEAN)) {
$entityType = ENTITY_QUOTE;
}
$invoice = $account->createInvoice($entityType, $data['client_id']);
if (isset($data['has_tasks']) && $data['has_tasks']) {
if (isset($data['has_tasks']) && filter_var($data['has_tasks'], FILTER_VALIDATE_BOOLEAN)) {
$invoice->has_tasks = true;
}
} else {

View File

@ -7,7 +7,7 @@ use App\Models\Product;
use League\Fractal;
use League\Fractal\TransformerAbstract;
class AccountTransformer extends TransformerAbstract
class AccountTransformer extends EntityTransformer
{
protected $defaultIncludes = [
'users',
@ -19,27 +19,32 @@ class AccountTransformer extends TransformerAbstract
public function includeUsers(Account $account)
{
return $this->collection($account->users, new UserTransformer($account));
$transformer = new UserTransformer($account, $this->serializer);
return $this->includeCollection($account->users, $transformer, 'users');
}
public function includeClients(Account $account)
{
return $this->collection($account->clients, new ClientTransformer($account));
$transformer = new ClientTransformer($account, $this->serializer);
return $this->includeCollection($account->clients, $transformer, 'clients');
}
public function includeInvoices(Account $account)
{
return $this->collection($account->invoices, new InvoiceTransformer($account));
$transformer = new InvoiceTransformer($account, $this->serializer);
return $this->includeCollection($account->invoices, $transformer, 'invoices');
}
public function includeContacts(Account $account)
{
return $this->collection($account->contacts, new ContactTransformer($account));
$transformer = new ContactTransformer($account, $this->serializer);
return $this->includeCollection($account->contacts, $transformer, 'contacts');
}
public function includeProducts(Account $account)
{
return $this->collection($account->products, new ProductTransformer($account));
$transformer = new ProductTransformer($account, $this->serializer);
return $this->includeCollection($account->products, $transformer, 'products');
}
public function transform(Account $account)

View File

@ -40,25 +40,28 @@ class ClientTransformer extends EntityTransformer
* @SWG\Property(property="language_id", type="integer", example=1)
*/
protected $defaultIncludes = [
// 'contacts',
// 'invoices',
// 'quotes',
protected $availableIncludes = [
'contacts',
'invoices',
'quotes',
];
public function includeContacts(Client $client)
{
return $this->collection($client->contacts, new ContactTransformer($this->account));
$transformer = new ContactTransformer($this->account, $this->serializer);
return $this->includeCollection($client->contacts, $transformer, ENTITY_CONTACT);
}
public function includeInvoices(Client $client)
{
return $this->collection($client->getInvoices, new InvoiceTransformer($this->account, $client));
$transformer = new InvoiceTransformer($this->account, $this->serializer);
return $this->includeCollection($client->getInvoices, $transformer, ENTITY_INVOICE);
}
public function includeQuotes(Client $client)
{
return $this->collection($client->getQuotes, new QuoteTransformer($this->account, $client));
$transformer = new QuoteTransformer($this->account, $this->serializer);
return $this->includeCollection($client->getQuotes, $transformer, ENTITY_QUOTE);
}
public function transform(Client $client)
@ -68,7 +71,7 @@ class ClientTransformer extends EntityTransformer
'name' => $client->name,
'balance' => (float) $client->balance,
'paid_to_date' => (float) $client->paid_to_date,
'user_id' => (int) $client->user->public_id+1,
'user_id' => (int) $client->user->public_id + 1,
'account_key' => $this->account->account_key,
'updated_at' => $client->updated_at,
'deleted_at' => $client->deleted_at,

View File

@ -20,7 +20,6 @@ class ContactTransformer extends EntityTransformer
'phone' => $contact->phone,
'last_login' => $contact->last_login,
'account_key' => $this->account->account_key,
'client_id' => $contact->client->public_id
];
}
}

View File

@ -1,14 +1,35 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\Client;
use League\Fractal\TransformerAbstract;
class EntityTransformer extends TransformerAbstract
{
protected $account;
protected $serializer;
public function __construct(Account $account)
public function __construct(Account $account = null, $serializer = null)
{
$this->account = $account;
$this->serializer = $serializer;
}
protected function includeCollection($data, $transformer, $entityType)
{
if ($this->serializer && $this->serializer != API_SERIALIZER_JSON) {
$entityType = null;
}
return $this->collection($data, $transformer, $entityType);
}
protected function includeItem($data, $transformer, $entityType)
{
if ($this->serializer && $this->serializer != API_SERIALIZER_JSON) {
$entityType = null;
}
return $this->item($data, $transformer, $entityType);
}
}

View File

@ -20,20 +20,14 @@ class InvoiceTransformer extends EntityTransformer
* @SWG\Property(property="invoice_status_id", type="integer", example=1)
*/
public function __construct(Account $account)
{
parent::__construct($account);
}
protected $defaultIncludes = [
'invoice_items',
];
public function includeInvoiceItems(Invoice $invoice)
{
return $this->collection($invoice->invoice_items, new InvoiceItemTransformer($this->account));
$transformer = new InvoiceItemTransformer($this->account, $this->serializer);
return $this->includeCollection($invoice->invoice_items, $transformer, ENTITY_INVOICE_ITEMS);
}
public function transform(Invoice $invoice)
@ -70,7 +64,7 @@ class InvoiceTransformer extends EntityTransformer
'has_tasks' => (bool) $invoice->has_tasks,
'auto_bill' => (bool) $invoice->auto_bill,
'account_key' => $this->account->account_key,
'user_id' => (int) $invoice->user->public_id+1
'user_id' => (int) $invoice->user->public_id + 1
];
}
}

View File

@ -0,0 +1,55 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\Payment;
use App\Models\Invoice;
use App\Models\Client;
use League\Fractal;
use App\Ninja\Transformers\InvoiceTransformer;
/**
* @SWG\Definition(definition="Payment", required={"invoice_id"}, @SWG\Xml(name="Payment"))
*/
class PaymentTransformer extends EntityTransformer
{
/**
* @SWG\Property(property="id", type="integer", example=1, readOnly=true)
* @SWG\Property(property="amount", type="float", example=10, readOnly=true)
* @SWG\Property(property="invoice_id", type="integer", example=1)
*/
protected $defaultIncludes = [
'invoice',
'client',
];
public function __construct(Account $account)
{
parent::__construct($account);
}
public function includeInvoice(Payment $payment)
{
$transformer = new InvoiceTransformer($this->account, $this->serializer);
return $this->includeItem($payment->invoice, $transformer, 'invoice');
}
public function includeClient(Payment $payment)
{
$transformer = new ClientTransformer($this->account, $this->serializer);
return $this->includeItem($payment->client, $transformer, 'client');
}
public function transform(Payment $payment)
{
return [
'id' => (int) $payment->public_id,
'amount' => (float) $payment->amount,
'account_key' => $this->account->account_key,
'user_id' => (int) $payment->user->public_id + 1,
'transaction_reference' => $payment->transaction_reference,
];
}
}

View File

@ -11,7 +11,8 @@ class QuoteTransformer extends EntityTransformer
public function includeInvoiceItems($invoice)
{
return $this->collection($invoice->invoice_items, new InvoiceItemTransformer($this->account));
$transformer = new InvoiceItemTransformer($this->account, $this->serializer);
return $this->includeCollection($invoice->invoice_items, $transformer, 'invoice_items');
}
public function transform(Invoice $invoice)

View File

@ -0,0 +1,50 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\Task;
use App\Models\Client;
use League\Fractal;
/**
* @SWG\Definition(definition="Task", @SWG\Xml(name="Task"))
*/
class TaskTransformer extends EntityTransformer
{
/**
* @SWG\Property(property="id", type="integer", example=1, readOnly=true)
* @SWG\Property(property="amount", type="float", example=10, readOnly=true)
* @SWG\Property(property="invoice_id", type="integer", example=1)
*/
protected $availableIncludes = [
'client',
];
public function __construct(Account $account)
{
parent::__construct($account);
}
public function includeClient(Task $task)
{
if ($task->client) {
$transformer = new ClientTransformer($this->account, $this->serializer);
return $this->includeItem($task->client, $transformer, 'client');
} else {
return null;
}
}
public function transform(Task $task)
{
return [
'id' => (int) $task->public_id,
'account_key' => $this->account->account_key,
'user_id' => (int) $task->user->public_id + 1,
'description' => $task->description,
'duration' => $task->getDuration()
];
}
}

View File

@ -14,16 +14,17 @@ class UserAccountTransformer extends EntityTransformer
protected $tokenName;
public function __construct(Account $account, $tokenName)
public function __construct(Account $account, $serializer, $tokenName)
{
parent::__construct($account);
parent::__construct($account, $serializer);
$this->tokenName = $tokenName;
}
public function includeUser(User $user)
{
return $this->item($user, new UserTransformer($this->account));
$transformer = new UserTransformer($this->account, $this->serializer);
return $this->includeItem($user, $transformer, 'user');
}
public function transform(User $user)

View File

@ -12,7 +12,8 @@ class DatatableService
if ($actions && $showCheckbox) {
$table->addColumn('checkbox', function ($model) {
return '<input type="checkbox" name="ids[]" value="' . $model->public_id . '" ' . Utils::getEntityRowClass($model) . '>';
return '<input type="checkbox" name="ids[]" value="' . $model->public_id
. '" ' . Utils::getEntityRowClass($model) . '>';
});
}
@ -81,14 +82,17 @@ class DatatableService
}
if ($entityType != ENTITY_USER || $model->public_id) {
$str .= "<li><a href=\"javascript:archiveEntity({$model->public_id})\">" . trans("texts.archive_{$entityType}") . "</a></li>";
$str .= "<li><a href=\"javascript:archiveEntity({$model->public_id})\">"
. trans("texts.archive_{$entityType}") . "</a></li>";
}
} else {
$str .= "<li><a href=\"javascript:restoreEntity({$model->public_id})\">" . trans("texts.restore_{$entityType}") . "</a></li>";
$str .= "<li><a href=\"javascript:restoreEntity({$model->public_id})\">"
. trans("texts.restore_{$entityType}") . "</a></li>";
}
if (property_exists($model, 'is_deleted') && !$model->is_deleted) {
$str .= "<li><a href=\"javascript:deleteEntity({$model->public_id})\">" . trans("texts.delete_{$entityType}") . "</a></li>";
$str .= "<li><a href=\"javascript:deleteEntity({$model->public_id})\">"
. trans("texts.delete_{$entityType}") . "</a></li>";
}
return $str.'</ul></div>';

View File

@ -1,10 +1,10 @@
<?php namespace App\Services;
<?php namespace app\Services;
use stdClass;
use Excel;
use Cache;
use Exception;
use Auth;
use Utils;
use parsecsv;
use Session;
use Validator;
@ -14,7 +14,7 @@ use App\Ninja\Repositories\InvoiceRepository;
use App\Ninja\Repositories\PaymentRepository;
use App\Ninja\Serializers\ArraySerializer;
use App\Models\Client;
use App\Models\Contact;
use App\Models\Invoice;
class ImportService
{
@ -53,7 +53,7 @@ class ImportService
public function import($source, $files)
{
$imported_files = null;
foreach ($files as $entityType => $file) {
$this->execute($source, $entityType, $file);
}
@ -61,67 +61,117 @@ class ImportService
private function execute($source, $entityType, $file)
{
$transformerClassName = $this->getTransformerClassName($source, $entityType);
$transformer = new $transformerClassName;
Excel::load($file, function($reader) use ($source, $entityType, $transformer) {
if ($entityType === ENTITY_CLIENT) {
$totalClients = count($reader->all()) + Client::scope()->withTrashed()->count();
if ($totalClients > Auth::user()->getMaxNumClients()) {
throw new Exception(trans('texts.limit_clients', ['count' => Auth::user()->getMaxNumClients()]));
}
}
$skipped = [];
Excel::load($file, function ($reader) use ($source, $entityType, $skipped) {
$this->checkData($entityType, count($reader->all()));
$maps = $this->createMaps();
$reader->each(function($row) use ($source, $entityType, $transformer, $maps) {
if ($resource = $transformer->transform($row, $maps)) {
$data = $this->fractal->createData($resource)->toArray();
if ($this->validate($data, $entityType) !== true) {
return;
}
$reader->each(function ($row) use ($source, $entityType, $maps) {
$result = $this->saveData($source, $entityType, $row, $maps);
$entity = $this->{"{$entityType}Repo"}->save($data);
// if the invoice is paid we'll also create a payment record
if ($entityType === ENTITY_INVOICE && isset($data['paid']) && $data['paid']) {
$class = self::getTransformerClassName($source, ENTITY_PAYMENT);
$paymentTransformer = new $class;
$row->client_id = $data['client_id'];
$row->invoice_id = $entity->public_id;
if ($resource = $paymentTransformer->transform($row, $maps)) {
$data = $this->fractal->createData($resource)->toArray();
$this->paymentRepo->save($data);
}
}
if ( ! $result) {
$skipped[] = $row;
}
});
});
return $skipped;
}
private function saveData($source, $entityType, $row, $maps)
{
$transformer = $this->getTransformer($source, $entityType);
$resource = $transformer->transform($row, $maps);
if (!$resource) {
return;
}
$data = $this->fractal->createData($resource)->toArray();
// if the invoice number is blank we'll assign it
if ($entityType == ENTITY_INVOICE && !$data['invoice_number']) {
$account = Auth::user()->account;
$invoice = Invoice::createNew();
$data['invoice_number'] = $account->getNextInvoiceNumber($invoice);
}
if ($this->validate($data, $entityType) !== true) {
return;
}
$entity = $this->{"{$entityType}Repo"}->save($data);
// if the invoice is paid we'll also create a payment record
if ($entityType === ENTITY_INVOICE && isset($row->paid) && $row->paid) {
$this->createPayment($source, $row, $maps, $data['client_id'], $entity->public_id);
}
}
private function checkData($entityType, $count)
{
if ($entityType === ENTITY_CLIENT) {
$this->checkClientCount($count);
}
}
private function checkClientCount($count)
{
$totalClients = $count + Client::scope()->withTrashed()->count();
if ($totalClients > Auth::user()->getMaxNumClients()) {
throw new Exception(trans('texts.limit_clients', ['count' => Auth::user()->getMaxNumClients()]));
}
}
public static function getTransformerClassName($source, $entityType)
{
return 'App\\Ninja\\Import\\'.$source.'\\'.ucwords($entityType).'Transformer';
}
public static function getTransformer($source, $entityType)
{
$className = self::getTransformerClassName($source, $entityType);
return new $className();
}
private function createPayment($source, $data, $maps, $clientId, $invoiceId)
{
$paymentTransformer = $this->getTransformer($source, ENTITY_PAYMENT);
$data->client_id = $clientId;
$data->invoice_id = $invoiceId;
if ($resource = $paymentTransformer->transform($data, $maps)) {
$data = $this->fractal->createData($resource)->toArray();
$this->paymentRepo->save($data);
}
}
// looking for a better solution...
// http://stackoverflow.com/questions/33781567/how-can-i-re-use-the-validation-code-in-my-laravel-formrequest-classes
private function validate($data, $entityType)
{
if ($entityType === ENTITY_CLIENT) {
$rules = [
'contacts' => 'valid_contacts',
];
} if ($entityType === ENTITY_INVOICE) {
}
if ($entityType === ENTITY_INVOICE) {
$rules = [
'client.contacts' => 'valid_contacts',
'invoice_items' => 'valid_invoice_items',
'invoice_number' => 'required|unique:invoices,invoice_number,,id,account_id,'.Auth::user()->account_id,
'discount' => 'positive',
];
} else {
return true;
}
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
$messages = $validator->messages();
return $messages->first();
} else {
return true;
@ -155,42 +205,50 @@ class ImportService
];
}
public static function getTransformerClassName($source, $entityType)
public function mapCSV($files)
{
return 'App\\Ninja\\Import\\' . $source . '\\' . ucwords($entityType) . 'Transformer';
$data = [];
foreach ($files as $entityType => $filename) {
if ($entityType === ENTITY_CLIENT) {
$columns = Client::getImportColumns();
$map = Client::getImportMap();
} else {
$columns = Invoice::getImportColumns();
$map = Invoice::getImportMap();
}
// Lookup field translations
foreach ($columns as $key => $value) {
unset($columns[$key]);
$columns[$value] = trans("texts.{$value}");
}
array_unshift($columns, ' ');
$data[$entityType] = $this->mapFile($entityType, $filename, $columns, $map);
if ($entityType === ENTITY_CLIENT) {
if (count($data[$entityType]['data']) + Client::scope()->count() > Auth::user()->getMaxNumClients()) {
throw new Exception(trans('texts.limit_clients', ['count' => Auth::user()->getMaxNumClients()]));
}
}
}
return $data;
}
public function mapFile($filename)
public function mapFile($entityType, $filename, $columns, $map)
{
require_once app_path().'/Includes/parsecsv.lib.php';
$csv = new parseCSV();
$csv->heading = false;
$csv->auto($filename);
if (count($csv->data) + Client::scope()->count() > Auth::user()->getMaxNumClients()) {
throw new Exception(trans('texts.limit_clients', ['count' => Auth::user()->getMaxNumClients()]));
}
Session::put('data', $csv->data);
Session::put("{$entityType}-data", $csv->data);
$headers = false;
$hasHeaders = false;
$mapped = array();
$columns = array('',
Client::$fieldName,
Client::$fieldPhone,
Client::$fieldAddress1,
Client::$fieldAddress2,
Client::$fieldCity,
Client::$fieldState,
Client::$fieldPostalCode,
Client::$fieldCountry,
Client::$fieldNotes,
Contact::$fieldFirstName,
Contact::$fieldLastName,
Contact::$fieldPhone,
Contact::$fieldEmail,
);
if (count($csv->data) > 0) {
$headers = $csv->data[0];
@ -206,32 +264,10 @@ class ImportService
$mapped[$i] = '';
if ($hasHeaders) {
$map = array(
'first' => Contact::$fieldFirstName,
'last' => Contact::$fieldLastName,
'email' => Contact::$fieldEmail,
'mobile' => Contact::$fieldPhone,
'phone' => Client::$fieldPhone,
'name|organization' => Client::$fieldName,
'street|address|address1' => Client::$fieldAddress1,
'street2|address2' => Client::$fieldAddress2,
'city' => Client::$fieldCity,
'state|province' => Client::$fieldState,
'zip|postal|code' => Client::$fieldPostalCode,
'country' => Client::$fieldCountry,
'note' => Client::$fieldNotes,
);
foreach ($map as $search => $column) {
foreach (explode("|", $search) as $string) {
if (strpos($title, 'sec') === 0) {
continue;
}
if (strpos($title, $string) !== false) {
$mapped[$i] = $column;
break(2);
}
if ($this->checkForMatch($title, $search)) {
$mapped[$i] = $column;
break;
}
}
}
@ -239,6 +275,7 @@ class ImportService
}
$data = array(
'entityType' => $entityType,
'data' => $csv->data,
'headers' => $headers,
'hasHeaders' => $hasHeaders,
@ -249,78 +286,105 @@ class ImportService
return $data;
}
public function importCSV($map, $hasHeaders)
private function checkForMatch($column, $pattern)
{
$count = 0;
$data = Session::get('data');
$countries = Cache::get('countries');
$countryMap = [];
foreach ($countries as $country) {
$countryMap[strtolower($country->name)] = $country->id;
if (strpos($column, 'sec') === 0) {
return false;
}
if (strpos($pattern, '^')) {
list($include, $exclude) = explode('^', $pattern);
$includes = explode('|', $include);
$excludes = explode('|', $exclude);
} else {
$includes = explode('|', $pattern);
$excludes = [];
}
foreach ($includes as $string) {
if (strpos($column, $string) !== false) {
$excluded = false;
foreach ($excludes as $exclude) {
if (strpos($column, $exclude) !== false) {
$excluded = true;
break;
}
}
if (!$excluded) {
return true;
}
}
}
return false;
}
public function importCSV($maps, $headers)
{
$skipped = [];
foreach ($maps as $entityType => $map) {
$result = $this->executeCSV($entityType, $map, $headers[$entityType]);
$skipped = array_merge($skipped, $result);
}
return $skipped;
}
private function executeCSV($entityType, $map, $hasHeaders)
{
$skipped = [];
$source = IMPORT_CSV;
$data = Session::get("{$entityType}-data");
$this->checkData($entityType, count($data));
$maps = $this->createMaps();
foreach ($data as $row) {
if ($hasHeaders) {
$hasHeaders = false;
continue;
}
$data = [
'contacts' => [[]]
];
$row = $this->convertToObject($entityType, $row, $map);
$result = $this->saveData($source, $entityType, $row, $maps);
foreach ($row as $index => $value) {
$field = $map[$index];
if ( ! $value = trim($value)) {
continue;
}
if ($field == Client::$fieldName) {
$data['name'] = $value;
} elseif ($field == Client::$fieldPhone) {
$data['work_phone'] = $value;
} elseif ($field == Client::$fieldAddress1) {
$data['address1'] = $value;
} elseif ($field == Client::$fieldAddress2) {
$data['address2'] = $value;
} elseif ($field == Client::$fieldCity) {
$data['city'] = $value;
} elseif ($field == Client::$fieldState) {
$data['state'] = $value;
} elseif ($field == Client::$fieldPostalCode) {
$data['postal_code'] = $value;
} elseif ($field == Client::$fieldCountry) {
$value = strtolower($value);
$data['country_id'] = isset($countryMap[$value]) ? $countryMap[$value] : null;
} elseif ($field == Client::$fieldNotes) {
$data['private_notes'] = $value;
} elseif ($field == Contact::$fieldFirstName) {
$data['contacts'][0]['first_name'] = $value;
} elseif ($field == Contact::$fieldLastName) {
$data['contacts'][0]['last_name'] = $value;
} elseif ($field == Contact::$fieldPhone) {
$data['contacts'][0]['phone'] = $value;
} elseif ($field == Contact::$fieldEmail) {
$data['contacts'][0]['email'] = strtolower($value);
}
if ( ! $result) {
$skipped[] = $row;
}
}
$rules = [
'contacts' => 'valid_contacts',
];
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
Session::forget("{$entityType}-data");
return $skipped;
}
private function convertToObject($entityType, $data, $map)
{
$obj = new stdClass();
if ($entityType === ENTITY_CLIENT) {
$columns = Client::getImportColumns();
} else {
$columns = Invoice::getImportColumns();
}
foreach ($columns as $column) {
$obj->$column = false;
}
foreach ($map as $index => $field) {
if (! $field) {
continue;
}
$this->clientRepo->save($data);
$count++;
if (isset($obj->$field) && $obj->$field) {
continue;
}
$obj->$field = $data[$index];
}
Session::forget('data');
return $count;
return $obj;
}
}

View File

@ -44,7 +44,9 @@ class PaymentService extends BaseService
}
$function = "set".ucfirst($key);
$gateway->$function($val);
if (method_exists($gateway, $function)) {
$gateway->$function($val);
}
}
if ($accountGateway->isGateway(GATEWAY_DWOLLA)) {
@ -100,10 +102,10 @@ class PaymentService extends BaseService
$data = [
'firstName' => $input['first_name'],
'lastName' => $input['last_name'],
'number' => $input['card_number'],
'expiryMonth' => $input['expiration_month'],
'expiryYear' => $input['expiration_year'],
'cvv' => $input['cvv'],
'number' => isset($input['card_number']) ? $input['card_number'] : null,
'expiryMonth' => isset($input['expiration_month']) ? $input['expiration_month'] : null,
'expiryYear' => isset($input['expiration_year']) ? $input['expiration_year'] : null,
'cvv' => isset($input['cvv']) ? $input['cvv'] : '',
];
if (isset($input['country_id'])) {
@ -159,7 +161,7 @@ class PaymentService extends BaseService
public function createToken($gateway, $details, $accountGateway, $client, $contactId)
{
$tokenResponse = $gateway->createCard($details)->send();
$cardReference = $tokenResponse->getCardReference();
$cardReference = $tokenResponse->getCustomerReference();
if ($cardReference) {
$token = AccountGatewayToken::where('client_id', '=', $client->id)
@ -237,7 +239,7 @@ class PaymentService extends BaseService
// setup the gateway/payment info
$gateway = $this->createGateway($accountGateway);
$details = $this->getPaymentDetails($invitation, $accountGateway);
$details['cardReference'] = $token;
$details['customerReference'] = $token;
// submit purchase/get response
$response = $gateway->purchase($details)->send();

30
c3.php
View File

@ -33,7 +33,14 @@ if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) {
if (!function_exists('__c3_error')) {
function __c3_error($message)
{
file_put_contents(C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt', $message);
$errorLogFile = defined('C3_CODECOVERAGE_ERROR_LOG_FILE') ?
C3_CODECOVERAGE_ERROR_LOG_FILE :
C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt';
if (is_writable($errorLogFile)) {
file_put_contents($errorLogFile, $message);
}else{
$message = "Could not write error to log file ($errorLogFile), original message: $message";
}
if (!headers_sent()) {
header('X-Codeception-CodeCoverage-Error: ' . str_replace("\n", ' ', $message), true, 500);
}
@ -43,10 +50,14 @@ if (!function_exists('__c3_error')) {
// Autoload Codeception classes
if (!class_exists('\\Codeception\\Codecept')) {
if (stream_resolve_include_path(__DIR__ . '/vendor/autoload.php')) {
require_once __DIR__ . '/vendor/autoload.php';
} elseif (file_exists(__DIR__ . '/codecept.phar')) {
if (file_exists(__DIR__ . '/codecept.phar')) {
require_once 'phar://'.__DIR__ . '/codecept.phar/autoload.php';
} elseif (stream_resolve_include_path(__DIR__ . '/vendor/autoload.php')) {
require_once __DIR__ . '/vendor/autoload.php';
// Required to load some methods only available at codeception/autoload.php
if (stream_resolve_include_path(__DIR__ . '/vendor/codeception/codeception/autoload.php')) {
require_once __DIR__ . '/vendor/codeception/codeception/autoload.php';
}
} elseif (stream_resolve_include_path('Codeception/autoload.php')) {
require_once 'Codeception/autoload.php';
} else {
@ -55,11 +66,18 @@ if (!class_exists('\\Codeception\\Codecept')) {
}
// Load Codeception Config
$config_dist_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.dist.yml';
$config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.yml';
if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'])) {
$config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'];
}
if (!file_exists($config_file)) {
if (file_exists($config_file)) {
// Use codeception.yml for configuration.
} elseif (file_exists($config_dist_file)) {
// Use codeception.dist.yml for configuration.
$config_file = $config_dist_file;
} else {
__c3_error(sprintf("Codeception config file '%s' not found", $config_file));
}
try {
@ -237,4 +255,4 @@ if ($requested_c3_report) {
}
}
// @codeCoverageIgnoreEnd
// @codeCoverageIgnoreEnd

View File

@ -66,7 +66,7 @@
"require-dev": {
"phpunit/phpunit": "~4.0",
"phpspec/phpspec": "~2.1",
"codeception/codeception": "~2.0",
"codeception/codeception": "2.1.2",
"codeception/c3": "~2.0",
"fzaninotto/faker": "^1.5"
},

253
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "b6c2660a613f4e94f13f226ec19c66eb",
"hash": "6966ff410ab9fb5745347a70ab9d85ca",
"packages": [
{
"name": "agmscode/omnipay-agms",
@ -779,16 +779,16 @@
},
{
"name": "collizo4sky/omnipay-wepay",
"version": "1.0",
"version": "1.1",
"source": {
"type": "git",
"url": "https://github.com/Collizo4sky/omnipay-wepay.git",
"reference": "360abf8c4bb4a926c39846abde970ab7dad93cb2"
"url": "https://github.com/collizo4sky/omnipay-wepay.git",
"reference": "bcc235113915c1547f62b8f02019f6289869c95c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Collizo4sky/omnipay-wepay/zipball/360abf8c4bb4a926c39846abde970ab7dad93cb2",
"reference": "360abf8c4bb4a926c39846abde970ab7dad93cb2",
"url": "https://api.github.com/repos/collizo4sky/omnipay-wepay/zipball/bcc235113915c1547f62b8f02019f6289869c95c",
"reference": "bcc235113915c1547f62b8f02019f6289869c95c",
"shasum": ""
},
"require": {
@ -800,7 +800,7 @@
},
"type": "library",
"autoload": {
"psr-0": {
"psr-4": {
"Omnipay\\WePay\\": "src/"
}
},
@ -809,7 +809,7 @@
"MIT"
],
"description": "WePay driver for the Omnipay payment processing library",
"homepage": "https://github.com/Collizo4sky/omnipay-wepay",
"homepage": "https://github.com/collizo4sky/omnipay-wepay",
"keywords": [
"gateway",
"merchant",
@ -818,7 +818,7 @@
"payment",
"wepay"
],
"time": "2015-10-08 14:12:18"
"time": "2015-11-13 13:19:25"
},
{
"name": "danielstjules/stringy",
@ -2610,12 +2610,12 @@
"source": {
"type": "git",
"url": "https://github.com/labs7in0/omnipay-wechat.git",
"reference": "d4c46d37f438c48510840aa3e5b806d4280c6b40"
"reference": "4e279ff4535dfa0636a3d6af5c92b8e9dcc4311a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/labs7in0/omnipay-wechat/zipball/d4c46d37f438c48510840aa3e5b806d4280c6b40",
"reference": "d4c46d37f438c48510840aa3e5b806d4280c6b40",
"url": "https://api.github.com/repos/labs7in0/omnipay-wechat/zipball/4e279ff4535dfa0636a3d6af5c92b8e9dcc4311a",
"reference": "4e279ff4535dfa0636a3d6af5c92b8e9dcc4311a",
"shasum": ""
},
"require": {
@ -2651,7 +2651,7 @@
"purchase",
"wechat"
],
"time": "2015-10-27 05:12:08"
"time": "2015-11-16 11:04:21"
},
{
"name": "laracasts/presenter",
@ -5309,16 +5309,16 @@
},
{
"name": "omnipay/stripe",
"version": "v2.2.1",
"version": "v2.3.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/omnipay-stripe.git",
"reference": "906377e50045dc2ba9c612aa1f6924157e1f750e"
"reference": "54b816a5e95e34c988d71fb805b0232cfd7c1ce5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/omnipay-stripe/zipball/906377e50045dc2ba9c612aa1f6924157e1f750e",
"reference": "906377e50045dc2ba9c612aa1f6924157e1f750e",
"url": "https://api.github.com/repos/thephpleague/omnipay-stripe/zipball/54b816a5e95e34c988d71fb805b0232cfd7c1ce5",
"reference": "54b816a5e95e34c988d71fb805b0232cfd7c1ce5",
"shasum": ""
},
"require": {
@ -5362,7 +5362,7 @@
"payment",
"stripe"
],
"time": "2015-04-14 18:55:56"
"time": "2015-11-10 16:17:35"
},
{
"name": "omnipay/targetpay",
@ -6068,16 +6068,16 @@
},
{
"name": "symfony/class-loader",
"version": "v2.7.6",
"version": "v2.7.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/class-loader.git",
"reference": "320f8d2a9cdbcbeb24be602c124aae9d998474a4"
"reference": "9d8359ca865621ba7f43ac6a3455d064d064bed7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/class-loader/zipball/320f8d2a9cdbcbeb24be602c124aae9d998474a4",
"reference": "320f8d2a9cdbcbeb24be602c124aae9d998474a4",
"url": "https://api.github.com/repos/symfony/class-loader/zipball/9d8359ca865621ba7f43ac6a3455d064d064bed7",
"reference": "9d8359ca865621ba7f43ac6a3455d064d064bed7",
"shasum": ""
},
"require": {
@ -6095,7 +6095,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\ClassLoader\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -6113,20 +6116,20 @@
],
"description": "Symfony ClassLoader Component",
"homepage": "https://symfony.com",
"time": "2015-10-23 14:47:27"
"time": "2015-10-30 20:10:21"
},
{
"name": "symfony/console",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/Console",
"source": {
"type": "git",
"url": "https://github.com/symfony/Console.git",
"url": "https://github.com/symfony/console.git",
"reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Console/zipball/0e5e18ae09d3f5c06367759be940e9ed3f568359",
"url": "https://api.github.com/repos/symfony/console/zipball/0e5e18ae09d3f5c06367759be940e9ed3f568359",
"reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359",
"shasum": ""
},
@ -6175,16 +6178,16 @@
},
{
"name": "symfony/css-selector",
"version": "v2.7.6",
"version": "v2.7.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "e1b865b26be4a56d22a8dee398375044a80c865b"
"reference": "abb47717fb88aebd9437da2fc8bb01a50a36679f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/e1b865b26be4a56d22a8dee398375044a80c865b",
"reference": "e1b865b26be4a56d22a8dee398375044a80c865b",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/abb47717fb88aebd9437da2fc8bb01a50a36679f",
"reference": "abb47717fb88aebd9437da2fc8bb01a50a36679f",
"shasum": ""
},
"require": {
@ -6199,7 +6202,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\CssSelector\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -6221,20 +6227,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2015-10-11 09:39:48"
"time": "2015-10-30 20:10:21"
},
{
"name": "symfony/debug",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/Debug",
"source": {
"type": "git",
"url": "https://github.com/symfony/Debug.git",
"url": "https://github.com/symfony/debug.git",
"reference": "fca5696e0c9787722baa8f2ad6940dfd7a6a6941"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Debug/zipball/fca5696e0c9787722baa8f2ad6940dfd7a6a6941",
"url": "https://api.github.com/repos/symfony/debug/zipball/fca5696e0c9787722baa8f2ad6940dfd7a6a6941",
"reference": "fca5696e0c9787722baa8f2ad6940dfd7a6a6941",
"shasum": ""
},
@ -6286,16 +6292,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v2.7.6",
"version": "v2.7.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8"
"reference": "7e2f9c31645680026c2372edf66f863fc7757af5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87a5db5ea887763fa3a31a5471b512ff1596d9b8",
"reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7e2f9c31645680026c2372edf66f863fc7757af5",
"reference": "7e2f9c31645680026c2372edf66f863fc7757af5",
"shasum": ""
},
"require": {
@ -6321,7 +6327,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -6339,20 +6348,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2015-10-11 09:39:48"
"time": "2015-10-30 20:10:21"
},
{
"name": "symfony/filesystem",
"version": "v2.7.6",
"version": "v2.7.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "56fd6df73be859323ff97418d97edc1d756df6df"
"reference": "8e173509d7fdbbba3cf34d6d072f2073c0210c1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/56fd6df73be859323ff97418d97edc1d756df6df",
"reference": "56fd6df73be859323ff97418d97edc1d756df6df",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/8e173509d7fdbbba3cf34d6d072f2073c0210c1d",
"reference": "8e173509d7fdbbba3cf34d6d072f2073c0210c1d",
"shasum": ""
},
"require": {
@ -6367,7 +6376,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -6385,20 +6397,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2015-10-18 20:23:18"
"time": "2015-11-18 13:41:01"
},
{
"name": "symfony/finder",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/Finder",
"source": {
"type": "git",
"url": "https://github.com/symfony/Finder.git",
"url": "https://github.com/symfony/finder.git",
"reference": "203a10f928ae30176deeba33512999233181dd28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Finder/zipball/203a10f928ae30176deeba33512999233181dd28",
"url": "https://api.github.com/repos/symfony/finder/zipball/203a10f928ae30176deeba33512999233181dd28",
"reference": "203a10f928ae30176deeba33512999233181dd28",
"shasum": ""
},
@ -6439,16 +6451,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/HttpFoundation",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpFoundation.git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "e8fd1b73ac1c3de1f76c73801ddf1a8ecb1c1c9c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/e8fd1b73ac1c3de1f76c73801ddf1a8ecb1c1c9c",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/e8fd1b73ac1c3de1f76c73801ddf1a8ecb1c1c9c",
"reference": "e8fd1b73ac1c3de1f76c73801ddf1a8ecb1c1c9c",
"shasum": ""
},
@ -6493,17 +6505,17 @@
},
{
"name": "symfony/http-kernel",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/HttpKernel",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpKernel.git",
"reference": "a3f0ed713255c0400a2db38b3ed01989ef4b7322"
"url": "https://github.com/symfony/http-kernel.git",
"reference": "498866a8ca0bcbcd3f3824b1520fa568ff7ca3b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/HttpKernel/zipball/a3f0ed713255c0400a2db38b3ed01989ef4b7322",
"reference": "a3f0ed713255c0400a2db38b3ed01989ef4b7322",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/498866a8ca0bcbcd3f3824b1520fa568ff7ca3b6",
"reference": "498866a8ca0bcbcd3f3824b1520fa568ff7ca3b6",
"shasum": ""
},
"require": {
@ -6567,20 +6579,20 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
"time": "2015-07-26 10:44:22"
"time": "2015-11-23 11:37:53"
},
{
"name": "symfony/process",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/Process",
"source": {
"type": "git",
"url": "https://github.com/symfony/Process.git",
"url": "https://github.com/symfony/process.git",
"reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Process/zipball/57f1e88bb5dafa449b83f9f265b11d52d517b3e9",
"url": "https://api.github.com/repos/symfony/process/zipball/57f1e88bb5dafa449b83f9f265b11d52d517b3e9",
"reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9",
"shasum": ""
},
@ -6621,16 +6633,16 @@
},
{
"name": "symfony/routing",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/Routing",
"source": {
"type": "git",
"url": "https://github.com/symfony/Routing.git",
"url": "https://github.com/symfony/routing.git",
"reference": "0a1764d41bbb54f3864808c50569ac382b44d128"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Routing/zipball/0a1764d41bbb54f3864808c50569ac382b44d128",
"url": "https://api.github.com/repos/symfony/routing/zipball/0a1764d41bbb54f3864808c50569ac382b44d128",
"reference": "0a1764d41bbb54f3864808c50569ac382b44d128",
"shasum": ""
},
@ -6690,7 +6702,7 @@
},
{
"name": "symfony/security-core",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/Security/Core",
"source": {
"type": "git",
@ -6754,16 +6766,16 @@
},
{
"name": "symfony/translation",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/Translation",
"source": {
"type": "git",
"url": "https://github.com/symfony/Translation.git",
"url": "https://github.com/symfony/translation.git",
"reference": "d84291215b5892834dd8ca8ee52f9cbdb8274904"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Translation/zipball/d84291215b5892834dd8ca8ee52f9cbdb8274904",
"url": "https://api.github.com/repos/symfony/translation/zipball/d84291215b5892834dd8ca8ee52f9cbdb8274904",
"reference": "d84291215b5892834dd8ca8ee52f9cbdb8274904",
"shasum": ""
},
@ -6813,7 +6825,7 @@
},
{
"name": "symfony/var-dumper",
"version": "v2.6.11",
"version": "v2.6.12",
"target-dir": "Symfony/Component/VarDumper",
"source": {
"type": "git",
@ -6966,16 +6978,16 @@
},
{
"name": "twbs/bootstrap",
"version": "v3.3.5",
"version": "v3.3.6",
"source": {
"type": "git",
"url": "https://github.com/twbs/bootstrap.git",
"reference": "16b48259a62f576e52c903c476bd42b90ab22482"
"reference": "81df608a40bf0629a1dc08e584849bb1e43e0b7a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twbs/bootstrap/zipball/16b48259a62f576e52c903c476bd42b90ab22482",
"reference": "16b48259a62f576e52c903c476bd42b90ab22482",
"url": "https://api.github.com/repos/twbs/bootstrap/zipball/81df608a40bf0629a1dc08e584849bb1e43e0b7a",
"reference": "81df608a40bf0629a1dc08e584849bb1e43e0b7a",
"shasum": ""
},
"replace": {
@ -7013,7 +7025,7 @@
"responsive",
"web"
],
"time": "2015-06-16 16:13:22"
"time": "2015-11-24 19:37:05"
},
{
"name": "vink/omnipay-komoju",
@ -7236,16 +7248,16 @@
},
{
"name": "zircote/swagger-php",
"version": "2.0.3",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/zircote/swagger-php.git",
"reference": "f6624cc067d7894ec32943f5b94cf282c683f7c7"
"reference": "be5d96e56c23cbe52c5bc5e267851323d95c57cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/f6624cc067d7894ec32943f5b94cf282c683f7c7",
"reference": "f6624cc067d7894ec32943f5b94cf282c683f7c7",
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/be5d96e56c23cbe52c5bc5e267851323d95c57cd",
"reference": "be5d96e56c23cbe52c5bc5e267851323d95c57cd",
"shasum": ""
},
"require": {
@ -7292,28 +7304,32 @@
"rest",
"service discovery"
],
"time": "2015-10-18 13:05:54"
"time": "2015-11-13 13:50:11"
}
],
"packages-dev": [
{
"name": "codeception/c3",
"version": "2.0.3",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/Codeception/c3.git",
"reference": "30321efb2421c5d201d02e2cb8da1a1ca96e4a38"
"reference": "bc22b4f6cd1a7e74a98dbff541c055dbf0f6f7c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/c3/zipball/30321efb2421c5d201d02e2cb8da1a1ca96e4a38",
"reference": "30321efb2421c5d201d02e2cb8da1a1ca96e4a38",
"url": "https://api.github.com/repos/Codeception/c3/zipball/bc22b4f6cd1a7e74a98dbff541c055dbf0f6f7c8",
"reference": "bc22b4f6cd1a7e74a98dbff541c055dbf0f6f7c8",
"shasum": ""
},
"require": {
"composer-plugin-api": "1.0.0",
"php": ">=5.4.0"
},
"type": "library",
"type": "composer-plugin",
"extra": {
"class": "Codeception\\c3\\Installer"
},
"autoload": {
"psr-4": {
"Codeception\\c3\\": "."
@ -7324,9 +7340,13 @@
"MIT"
],
"authors": [
{
"name": "Tiger Seo",
"email": "tiger.seo@gmail.com"
},
{
"name": "Michael Bodnarchuk",
"email": "davert.php@resend.cc",
"email": "davert.php@codegyre.com",
"homepage": "http://codegyre.com"
}
],
@ -7336,27 +7356,27 @@
"code coverage",
"codecoverage"
],
"time": "2014-11-18 22:06:45"
"time": "2015-11-25 04:03:09"
},
{
"name": "codeception/codeception",
"version": "2.1.4",
"version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/Codeception/Codeception.git",
"reference": "6a812e8a0d1b1db939a29b4dc14cb398b21b6112"
"reference": "521adbb2ee34e9debdd8508a2c41ab2b5c2f042b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/6a812e8a0d1b1db939a29b4dc14cb398b21b6112",
"reference": "6a812e8a0d1b1db939a29b4dc14cb398b21b6112",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/521adbb2ee34e9debdd8508a2c41ab2b5c2f042b",
"reference": "521adbb2ee34e9debdd8508a2c41ab2b5c2f042b",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"facebook/webdriver": ">=1.0.1",
"guzzlehttp/guzzle": ">=4.1.4 <7.0",
"guzzlehttp/guzzle": ">=4.0|<7.0",
"guzzlehttp/psr7": "~1.0",
"php": ">=5.4.0",
"phpunit/phpunit": "~4.8.0",
@ -7416,7 +7436,7 @@
"functional testing",
"unit testing"
],
"time": "2015-11-12 03:57:06"
"time": "2015-08-09 13:48:55"
},
{
"name": "doctrine/instantiator",
@ -8479,16 +8499,16 @@
},
{
"name": "symfony/browser-kit",
"version": "v2.7.6",
"version": "v2.7.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "07d664a052572ccc28eb2ab7dbbe82155b1ad367"
"reference": "bd28847ea2193916074c7b11d4fdd78570049694"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/07d664a052572ccc28eb2ab7dbbe82155b1ad367",
"reference": "07d664a052572ccc28eb2ab7dbbe82155b1ad367",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/bd28847ea2193916074c7b11d4fdd78570049694",
"reference": "bd28847ea2193916074c7b11d4fdd78570049694",
"shasum": ""
},
"require": {
@ -8511,7 +8531,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\BrowserKit\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -8529,20 +8552,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2015-10-23 14:47:27"
"time": "2015-11-02 20:20:53"
},
{
"name": "symfony/dom-crawler",
"version": "v2.7.6",
"version": "v2.7.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "5fef7d8b80d8f9992df99d8ee283f420484c9612"
"reference": "b33593cbfe1d81b50d48353f338aca76a08658d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/5fef7d8b80d8f9992df99d8ee283f420484c9612",
"reference": "5fef7d8b80d8f9992df99d8ee283f420484c9612",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b33593cbfe1d81b50d48353f338aca76a08658d8",
"reference": "b33593cbfe1d81b50d48353f338aca76a08658d8",
"shasum": ""
},
"require": {
@ -8563,7 +8586,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\DomCrawler\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -8581,20 +8607,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2015-10-11 09:39:48"
"time": "2015-11-02 20:20:53"
},
{
"name": "symfony/yaml",
"version": "v2.7.6",
"version": "v2.7.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "eca9019c88fbe250164affd107bc8057771f3f4d"
"reference": "4cfcd7a9fceba662b3c036b7d9a91f6197af046c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/eca9019c88fbe250164affd107bc8057771f3f4d",
"reference": "eca9019c88fbe250164affd107bc8057771f3f4d",
"url": "https://api.github.com/repos/symfony/yaml/zipball/4cfcd7a9fceba662b3c036b7d9a91f6197af046c",
"reference": "4cfcd7a9fceba662b3c036b7d9a91f6197af046c",
"shasum": ""
},
"require": {
@ -8609,7 +8635,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -8627,7 +8656,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2015-10-11 09:39:48"
"time": "2015-11-18 13:41:01"
}
],
"aliases": [],

View File

@ -2,124 +2,124 @@
return [
/*
|--------------------------------------------------------------------------
| PDO Fetch Style
|--------------------------------------------------------------------------
|
| By default, database results will be returned as instances of the PHP
| stdClass object; however, you may desire to retrieve records in an
| array format for simplicity. Here you can tweak the fetch style.
|
*/
/*
|--------------------------------------------------------------------------
| PDO Fetch Style
|--------------------------------------------------------------------------
|
| By default, database results will be returned as instances of the PHP
| stdClass object; however, you may desire to retrieve records in an
| array format for simplicity. Here you can tweak the fetch style.
|
*/
'fetch' => PDO::FETCH_CLASS,
'fetch' => PDO::FETCH_CLASS,
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
|
*/
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
|
*/
'default' => env('DB_TYPE', 'mysql'),
'default' => env('DB_TYPE', 'mysql'),
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
|
*/
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
|
*/
'connections' => [
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => storage_path().'/database.sqlite',
'prefix' => '',
],
'sqlite' => [
'driver' => 'sqlite',
'database' => storage_path().'/database.sqlite',
'prefix' => '',
],
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => env('DB_STRICT', false),
],
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
],
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'prefix' => '',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'prefix' => '',
],
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run in the database.
|
*/
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run in the database.
|
*/
'migrations' => 'migrations',
'migrations' => 'migrations',
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer set of commands than a typical key-value systems
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer set of commands than a typical key-value systems
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => [
'redis' => [
'cluster' => false,
'cluster' => false,
'default' => [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
],
'default' => [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
],
],
],
];

BIN
public/favicon-v2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -31755,6 +31755,8 @@ NINJA.decodeJavascript = function(invoice, javascript)
if (match.indexOf('?') < 0 || value) {
if (invoice.partial && field == 'balance_due') {
field = 'amount_due';
} else if (invoice.is_quote && field == 'your_invoice') {
field = 'your_quote';
}
var label = invoiceLabels[field];
if (match.indexOf('UC') >= 0) {

View File

@ -168,8 +168,10 @@ NINJA.decodeJavascript = function(invoice, javascript)
if (match.indexOf('?') < 0 || value) {
if (invoice.partial && field == 'balance_due') {
field = 'amount_due';
} else if (invoice.is_quote && field == 'your_invoice') {
field = 'your_quote';
}
var label = invoiceLabels[field];
var label = invoiceLabels[field];
if (match.indexOf('UC') >= 0) {
label = label.toUpperCase();
}

View File

@ -7,7 +7,13 @@
[![Join the chat at https://gitter.im/hillelcoren/invoice-ninja](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hillelcoren/invoice-ninja?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
If you'd like to use our code to sell your own invoicing app email us for details about our affiliate program.
### Referral Program
* $100 per signup paid over 3 years - [Learn more](https://www.invoiceninja.com/referral-program/)
### Reseller Program
There are two options:
* 10% of revenue
* $1,000 for a site limited to 1,000 accounts
### Installation Options
* [Self-Host Zip](https://www.invoiceninja.com/knowledgebase/self-host/) - Free
@ -15,6 +21,11 @@ If you'd like to use our code to sell your own invoicing app email us for detail
* [Bitnami](https://bitnami.com/stack/invoice-ninja) - Free
* [Softaculous](https://www.softaculous.com/apps/ecommerce/Invoice_Ninja) - $30
### Requirements
* PHP >= 5.4.0
* MCrypt Extension
* MySQL
### Features
* Built using Laravel 5
* Live PDF generation using [pdfmake](http://pdfmake.org/)

View File

@ -447,7 +447,6 @@
'gateway_help_1' => ':link til at registrere dig hos Authorize.net.',
'gateway_help_2' => ':link til at registrere dig hos Authorize.net.',
'gateway_help_17' => ':link til at hente din PayPal API signatur.',
'gateway_help_23' => 'Note: brug din hemmelige API nøgle, IKKE din publicerede API nøgle.',
'gateway_help_27' => ':link til at registrere dig hos TwoCheckout.',
'more_designs' => 'Flere designs',
@ -918,5 +917,38 @@
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -448,7 +448,6 @@ return array(
'gateway_help_1' => ':link um sich bei Authorize.net anzumelden.',
'gateway_help_2' => ':link um sich bei Authorize.net anzumelden.',
'gateway_help_17' => ':link um deine PayPal API-Signatur zu erhalten.',
'gateway_help_23' => 'Anmerkung: benutze deinen secret API key, nicht deinen publishable API key.',
'gateway_help_27' => ':link um sich bei TwoCheckout anzumelden.',
'more_designs' => 'Weitere Designs',
@ -920,4 +919,37 @@ return array(
'country' => 'Land',
'include' => 'Hinzufügen',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -87,7 +87,7 @@ return array(
'guest' => 'Guest',
'company_details' => 'Company Details',
'online_payments' => 'Online Payments',
'notifications' => 'Notifications',
'notifications' => 'Email Notifications',
'import_export' => 'Import/Export',
'done' => 'Done',
'save' => 'Save',
@ -334,7 +334,7 @@ return array(
// product management
'product_library' => 'Product Library',
'product' => 'Product',
'products' => 'Products',
'products' => 'Product Library',
'fill_products' => 'Auto-fill products',
'fill_products_help' => 'Selecting a product will automatically <b>fill in the description and cost</b>',
'update_products' => 'Auto-update products',
@ -450,7 +450,6 @@ return array(
'gateway_help_1' => ':link to sign up for Authorize.net.',
'gateway_help_2' => ':link to sign up for Authorize.net.',
'gateway_help_17' => ':link to get your PayPal API signature.',
'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.',
'gateway_help_27' => ':link to sign up for TwoCheckout.',
'more_designs' => 'More designs',
@ -673,7 +672,7 @@ return array(
'counter' => 'Counter',
'payment_type_dwolla' => 'Dwolla',
'gateway_help_43' => ':link to sign up for Dwolla.<br/>Note: remove dashes from the Destination/Dwolla Id',
'gateway_help_43' => ':link to sign up for Dwolla',
'partial_value' => 'Must be greater than zero and less than the total',
'more_actions' => 'More Actions',
@ -921,7 +920,7 @@ return array(
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better performance we suggest uploading an image file less than 200KB',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
@ -945,4 +944,14 @@ return array(
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -420,7 +420,6 @@ return array(
'gateway_help_1' => ':link para registrarse con Authorize.net.',
'gateway_help_2' => ':link para registrarse con Authorize.net.',
'gateway_help_17' => ':link para obtener su firma del API de PayPal.',
'gateway_help_23' => 'Nota: use use llave secreta del API, no la llave pública.',
'gateway_help_27' => ':link para registrarse con TwoCheckout.',
'more_designs' => 'Más diseños',
@ -896,5 +895,38 @@ return array(
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -438,7 +438,6 @@ return array(
'gateway_help_1' => ':link para registrarse en Authorize.net.',
'gateway_help_2' => ':link para registrarse en Authorize.net.',
'gateway_help_17' => ':link para obtener su firma API de PayPal.',
'gateway_help_23' => 'Nota: utilizar su clave de API secreta, no es su clave de API publica.',
'gateway_help_27' => ':link para registrarse en TwoCheckout.',
'more_designs' => 'Más diseños',
@ -917,4 +916,37 @@ return array(
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -441,7 +441,6 @@ return array(
'gateway_help_1' => ':link to sign up for Authorize.net.',
'gateway_help_2' => ':link to sign up for Authorize.net.',
'gateway_help_17' => ':link pour obtenir votre signature PayPal API.',
'gateway_help_23' => 'Note: uutilisez votre Secret API et non votre clé publiable.',
'gateway_help_27' => ':link pour vous enregistrer sur TwoCheckout.',
'more_designs' => 'Plus de modèles',
@ -910,5 +909,38 @@ return array(
'user' => 'Utilisateur',
'country' => 'Pays',
'include' => 'Inclure',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -441,7 +441,6 @@ return array(
'gateway_help_1' => ':link to sign up for Authorize.net.',
'gateway_help_2' => ':link to sign up for Authorize.net.',
'gateway_help_17' => ':link to get your PayPal API signature.',
'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.',
'gateway_help_27' => ':link to sign up for TwoCheckout.',
'more_designs' => 'Plus de modèles',
@ -911,4 +910,37 @@ return array(
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -441,7 +441,6 @@ return array(
'gateway_help_1' => ':link to sign up for Authorize.net.',
'gateway_help_2' => ':link to sign up for Authorize.net.',
'gateway_help_17' => ':link to get your PayPal API signature.',
'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.',
'gateway_help_27' => ':link to sign up for TwoCheckout.',
'more_designs' => 'More designs',
@ -912,5 +911,38 @@ return array(
'user' => 'User',
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -449,7 +449,6 @@ return array(
'gateway_help_1' => ':link to sign up for Authorize.net.',
'gateway_help_2' => ':link to sign up for Authorize.net.',
'gateway_help_17' => ':link to get your PayPal API signature.',
'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.',
'gateway_help_27' => ':link to sign up for TwoCheckout.',
'more_designs' => 'More designs',
@ -919,6 +918,39 @@ return array(
'user' => 'User',
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -447,7 +447,6 @@ return array(
'gateway_help_1' => ':link for å lage en konto for Authorize.net.',
'gateway_help_2' => ':link for å lage en konto for Authorize.net.',
'gateway_help_17' => ':link for å få din PayPal API signatur.',
'gateway_help_23' => 'Info: bruk din hemmelige API nøkkel, ikke din offentlige API nøkkel.',
'gateway_help_27' => ':link for å lage en konto for TwoCheckout.',
'more_designs' => 'Flere design',
@ -917,5 +916,38 @@ return array(
'user' => 'User',
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -443,7 +443,6 @@ return array(
'gateway_help_1' => ':link om in te schrijven voor Authorize.net.',
'gateway_help_2' => ':link om in te schrijven voor Authorize.net.',
'gateway_help_17' => ':link om uw PayPal API signature te krijgen.',
'gateway_help_23' => 'Opmerking: gebruik uw gehieme API key, niet uw publiceerbare API key.',
'gateway_help_27' => ':link om in te schrijven voor TwoCheckout.',
'more_designs' => 'Meer ontwerpen',
@ -913,5 +912,38 @@ return array(
'user' => 'User',
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -441,7 +441,6 @@ return array(
'gateway_help_1' => ':link para acessar Authorize.net.',
'gateway_help_2' => ':link para acessar Authorize.net.',
'gateway_help_17' => ':link para adquirir sua "PayPal API signature".',
'gateway_help_23' => 'Aviso: use sua "Secret API Key", não a "Publishable API Key".',
'gateway_help_27' => ':link para acessar TwoCheckout.',
'more_designs' => 'Mais Modelos',
@ -918,7 +917,28 @@ return array(
'user_unregistered' => 'Registre sua conta para enviar e-mails',
'user_unconfirmed' => 'Confirme sua conta para enviar e-mails',
'invalid_contact_email' => 'E-mail do contato inválido',
]
],
'client_portal' => 'Portal do Cliente',
'import_freshbooks' => 'Importar de FreshBooks',
'import_data' => 'Importar Dados',
'source' => 'Fonte',
'csv' => 'CSV',
'client_file' => 'Arquivo de Clientes',
'invoice_file' => 'Arquivo de Faturas',
'task_file' => 'Arquivo de Tarefas',
'no_mapper' => 'Mapeamento inválido',
'invalid_csv_header' => 'CSV com cabeçalho inválido',
'client_portal' => 'Portal do Cliente',
'admin' => 'Admin',
'disabled' => 'Disabilitado',
'show_archived_users' => 'Mostrar usuários arquivados',
'notes' => 'Observações',
'invoice_will_create' => 'cliente será criado',
'invoices_will_create' => 'faturas serão criadas',
'failed_to_import' => 'A importação dos seguintes registros falhou',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -447,7 +447,6 @@ return array(
'gateway_help_1' => ':link för att registrera dig på Authorize.net.',
'gateway_help_2' => ':link för att registrera dig på Authorize.net.',
'gateway_help_17' => ':link för att hämta din PayPal API-nyckel.',
'gateway_help_23' => 'Observera: använd din hemliga API-nyckel, inte den publika.',
'gateway_help_27' => ':link för att registrera dig för TwoCheckout.',
'more_designs' => 'Fler fakturalayouter',
@ -915,5 +914,39 @@ return array(
'user' => 'User',
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB',
'import_freshbooks' => 'Import From FreshBooks',
'import_data' => 'Import Data',
'source' => 'Source',
'csv' => 'CSV',
'client_file' => 'Client File',
'invoice_file' => 'Invoice File',
'task_file' => 'Task File',
'no_mapper' => 'No valid mapping for file',
'invalid_csv_header' => 'Invalid CSV Header',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
],
'client_portal' => 'Client Portal',
'admin' => 'Admin',
'disabled' => 'Disabled',
'show_archived_users' => 'Show archived users',
'notes' => 'Notes',
'invoice_will_create' => 'client will be created',
'invoices_will_create' => 'invoices will be created',
'failed_to_import' => 'The following records failed to import',
'publishable_key' => 'Publishable Key',
'secret_key' => 'Secret Key',
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
);

View File

@ -19,8 +19,9 @@
{!! Former::populateField('gateway_id', $accountGateway->gateway_id) !!}
{!! Former::populateField('payment_type_id', $paymentTypeId) !!}
{!! Former::populateField('recommendedGateway_id', $accountGateway->gateway_id) !!}
{!! Former::populateField('show_address', intval($accountGateway->show_address)) !!}
{!! Former::populateField('show_address', intval($accountGateway->show_address)) !!}
{!! Former::populateField('update_address', intval($accountGateway->update_address)) !!}
{!! Former::populateField('publishable_key', $accountGateway->getPublishableStripeKey() ? str_repeat('*', strlen($accountGateway->getPublishableStripeKey())) : '') !!}
@if ($config)
@foreach ($accountGateway->fields as $field => $junk)
@ -63,7 +64,7 @@
@elseif ($field == 'username' || $field == 'password')
{!! Former::text($gateway->id.'_'.$field)->label('API '. ucfirst(Utils::toSpaceCase($field))) !!}
@else
{!! Former::text($gateway->id.'_'.$field)->label(Utils::toSpaceCase($field)) !!}
{!! Former::text($gateway->id.'_'.$field)->label($gateway->id == GATEWAY_STRIPE ? trans('texts.secret_key') : Utils::toSpaceCase($field)) !!}
@endif
@endforeach
@ -78,6 +79,8 @@
@endif
@if ($gateway->id == GATEWAY_STRIPE)
{!! Former::text('publishable_key') !!}
{!! Former::select('token_billing_type_id')
->options($tokenBillingOptions)
->help(trans('texts.token_billing_help')) !!}

View File

@ -4,7 +4,6 @@
@parent
<style type="text/css">
.invoice-file,
.task-file {
display: none;
}
@ -131,15 +130,11 @@
@endforeach
@foreach (\App\Services\ImportService::$sources as $source)
if (val === '{{ $source }}') {
@if ($source == IMPORT_CSV)
$('.client-file').show();
@else
@foreach (\App\Services\ImportService::$entityTypes as $entityType)
@if (class_exists(\App\Services\ImportService::getTransformerClassName($source, $entityType)))
$('.{{ $entityType }}-file').show();
@endif
@endforeach
@endif
@foreach (\App\Services\ImportService::$entityTypes as $entityType)
@if (class_exists(\App\Services\ImportService::getTransformerClassName($source, $entityType)))
$('.{{ $entityType }}-file').show();
@endif
@endforeach
}
@endforeach
}

View File

@ -7,83 +7,18 @@
{!! Former::open('/import_csv')->addClass('warn-on-exit') !!}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.import_clients') !!}</h3>
</div>
<div class="panel-body">
@if (isset($data[ENTITY_CLIENT]))
@include('accounts.partials.map', $data[ENTITY_CLIENT])
@endif
@if ($headers)
@if (isset($data[ENTITY_INVOICE]))
@include('accounts.partials.map', $data[ENTITY_INVOICE])
@endif
<label for="header_checkbox">
<input type="checkbox" name="header_checkbox" id="header_checkbox" {{ $hasHeaders ? 'CHECKED' : '' }}> {{ trans('texts.first_row_headers') }}
</label>
<p>&nbsp;</p>
<table class="table invoice-table">
<thead>
<tr>
<th>{{ trans('texts.column') }}</th>
<th class="col_sample">{{ trans('texts.sample') }}</th>
<th>{{ trans('texts.import_to') }}</th>
</tr>
</thead>
@for ($i=0; $i<count($headers); $i++)
<tr>
<td>{{ $headers[$i] }}</td>
<td class="col_sample">{{ $data[1][$i] }}</td>
<td>{!! Former::select('map[' . $i . ']')->options($columns, $mapped[$i], true)->raw() !!}</td>
</tr>
@endfor
</table>
<p>&nbsp;</p>
<span id="numClients"></span>
@endif
</div>
</div>
{!! Former::actions(
Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/settings/import_export'))->appendIcon(Icon::create('remove-circle')),
Button::success(trans('texts.import'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))) !!}
{!! Former::close() !!}
<script type="text/javascript">
$(function() {
var numClients = {{ count($data) }};
function setSampleShown() {
if ($('#header_checkbox').is(':checked')) {
$('.col_sample').show();
setNumClients(numClients - 1);
} else {
$('.col_sample').hide();
setNumClients(numClients);
}
}
function setNumClients(num)
{
if (num == 1)
{
$('#numClients').html("1 {{ trans('texts.client_will_create') }}");
}
else
{
$('#numClients').html(num + " {{ trans('texts.clients_will_create') }}");
}
}
$('#header_checkbox').click(setSampleShown);
setSampleShown();
});
</script>
{!! Former::actions(
Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/settings/import_export'))->appendIcon(Icon::create('remove-circle')),
Button::success(trans('texts.import'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))) !!}
{!! Former::close() !!}
@stop

View File

@ -0,0 +1,66 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans("texts.import_{$entityType}s") !!}</h3>
</div>
<div class="panel-body">
<label for="{{ $entityType }}_header_checkbox">
<input type="checkbox" name="headers[{{ $entityType }}]" id="{{ $entityType }}_header_checkbox" {{ $hasHeaders ? 'CHECKED' : '' }}> {{ trans('texts.first_row_headers') }}
</label>
<p>&nbsp;</p>
<table class="table invoice-table">
<thead>
<tr>
<th>{{ trans('texts.column') }}</th>
<th class="col_sample">{{ trans('texts.sample') }}</th>
<th>{{ trans('texts.import_to') }}</th>
</tr>
</thead>
@for ($i=0; $i<count($headers); $i++)
<tr>
<td>{{ $headers[$i] }}</td>
<td class="col_sample">{{ $data[1][$i] }}</td>
<td>{!! Former::select('map['.$entityType.'][' . $i . ']')->options($columns, $mapped[$i])->raw() !!}</td>
</tr>
@endfor
</table>
<p>&nbsp;</p>
<span id="num{{ $entityType }}"></span>
</div>
</div>
<script type="text/javascript">
$(function() {
var num{{ $entityType }} = {{ count($data) }};
function set{{ $entityType }}SampleShown() {
if ($('#{{ $entityType }}_header_checkbox').is(':checked')) {
$('.col_sample').show();
setNum{{ $entityType }}(num{{ $entityType }} - 1);
} else {
$('.col_sample').hide();
setNum{{ $entityType }}(num{{ $entityType }});
}
}
function setNum{{ $entityType }}(num)
{
if (num == 1) {
$('#num{{ $entityType }}').html("1 {{ trans("texts.{$entityType}_will_create") }}");
} else {
$('#num{{ $entityType }}').html(num + " {{ trans("texts.{$entityType}s_will_create") }}");
}
}
$('#{{ $entityType }}_header_checkbox').click(set{{ $entityType }}SampleShown);
set{{ $entityType }}SampleShown();
});
</script>

View File

@ -186,6 +186,7 @@
trans('texts.balance'),
trans('texts.adjustment'))
->setUrl(url('api/activities/'. $client->public_id))
->setCustomValues('entityType', 'activity')
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('aaSorting', [['0', 'desc']])
@ -203,6 +204,7 @@
trans('texts.description'),
trans('texts.status'))
->setUrl(url('api/tasks/'. $client->public_id))
->setCustomValues('entityType', 'tasks')
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('aaSorting', [['0', 'desc']])
@ -223,6 +225,7 @@
trans('texts.valid_until'),
trans('texts.status'))
->setUrl(url('api/quotes/'. $client->public_id))
->setCustomValues('entityType', 'quotes')
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('aaSorting', [['0', 'desc']])
@ -241,6 +244,7 @@
trans('texts.end_date'),
trans('texts.invoice_total'))
->setUrl(url('api/recurring_invoices/' . $client->public_id))
->setCustomValues('entityType', 'recurring_invoices')
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('aaSorting', [['0', 'asc']])
@ -256,6 +260,7 @@
trans('texts.due_date'),
trans('texts.status'))
->setUrl(url('api/invoices/' . $client->public_id))
->setCustomValues('entityType', 'invoices')
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('aaSorting', [['0', 'desc']])
@ -272,6 +277,7 @@
trans('texts.payment_amount'),
trans('texts.payment_date'))
->setUrl(url('api/payments/' . $client->public_id))
->setCustomValues('entityType', 'payments')
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('aaSorting', [['0', 'desc']])
@ -287,6 +293,7 @@
trans('texts.credit_date'),
trans('texts.private_notes'))
->setUrl(url('api/credits/' . $client->public_id))
->setCustomValues('entityType', 'credits')
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('aaSorting', [['0', 'asc']])
@ -297,6 +304,8 @@
<script type="text/javascript">
var loadedTabs = {};
$(function() {
$('.normalDropDown:not(.dropdown-toggle)').click(function() {
window.location = '{{ URL::to('clients/' . $client->public_id . '/edit') }}';
@ -305,13 +314,24 @@
window.location = '{{ URL::to('invoices/create/' . $client->public_id ) }}';
});
// load datatable data when tab is shown and remember last tab selected
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var target = $(e.target).attr("href") // activated tab
target = target.substring(1);
localStorage.setItem('client_tab', target);
if (!loadedTabs.hasOwnProperty(target)) {
loadedTabs[target] = true;
window['load_' + target]();
if (target == 'invoices' && window.hasOwnProperty('load_recurring_invoices')) {
window['load_recurring_invoices']();
}
}
});
var tab = localStorage.getItem('client_tab');
if (tab) {
$('.nav-tabs a[href="' + tab + '"]').tab('show');
$('.nav-tabs a[href="#' + tab.replace('#', '') + '"]').tab('show');
} else {
window['load_activity']();
}
});

View File

@ -32,8 +32,17 @@
</tbody>
</table>
<script type="text/javascript">
jQuery(document).ready(function(){
// dynamic table
@if (isset($values['entityType']))
window.load_{{ $values['entityType'] }} = function load_{{ $values['entityType'] }}() {
load_{{ $class }}();
}
@else
jQuery(document).ready(function(){
load_{{ $class }}();
});
@endif
function load_{{ $class }}() {
jQuery('.{{ $class }}').dataTable({
"fnRowCallback": function(row, data) {
if (data[0].indexOf('ENTITY_DELETED') > 0) {
@ -49,7 +58,7 @@
// Disable sorting on the first column
"aoColumnDefs": [ {
'bSortable': false,
'aTargets': [ 0, {{ count($columns) - 1 }} ]
'aTargets': [ 0, {{ count($columns) - 1 }} ]
} ],
@endif
@foreach ($options as $k => $o)
@ -64,5 +73,5 @@
}
}
});
});
}
</script>

View File

@ -271,7 +271,7 @@
});
$('#search').focus(function(){
$('#search').css('width', '{{ Utils::isEnglish() ? 256 : 216 }}px');
$('#search').css('width', '{{ Utils::isEnglish() ? 264 : 216 }}px');
$('ul.navbar-right').hide();
if (!window.hasOwnProperty('searchData')) {
trackEvent('/activity', '/search');
@ -481,7 +481,7 @@
<form class="navbar-form navbar-right" role="search">
<div class="form-group">
<input type="text" id="search" style="width: {{ Utils::isEnglish() ? 150 : 110 }}px"
<input type="text" id="search" style="width: {{ Utils::isEnglish() ? 150 : 110 }}px;padding-top:0px;padding-bottom:0px"
class="form-control" placeholder="{{ trans('texts.search') }}">
</div>
</form>

View File

@ -218,7 +218,7 @@
<div class="line-total" data-bind="text: totals.total"></div>
</td>
<td style="cursor:pointer" class="hide-border td-icon">
<i style="display:none;padding-left:4px" data-bind="click: $parent.removeItem, visible: actionsVisible() &amp;&amp;
<i style="padding-left:2px" data-bind="click: $parent.removeItem, visible: actionsVisible() &amp;&amp;
$index() < ($parent.invoice_items().length - 1) &amp;&amp;
$parent.invoice_items().length > 1" class="fa fa-minus-circle redlink" title="Remove item"/>
</td>

View File

@ -354,7 +354,7 @@ function InvoiceModel(data) {
self.totals.subtotal = ko.computed(function() {
var total = self.totals.rawSubtotal();
return total > 0 ? formatMoney(total, self.client().currency_id()) : '';
return formatMoney(total, self.client().currency_id());
});
self.totals.rawDiscounted = ko.computed(function() {

View File

@ -6,7 +6,7 @@
@else
<title>{{ isset($title) ? ($title . ' | Invoice Ninja') : ('Invoice Ninja | ' . trans('texts.app_title')) }}</title>
<meta name="description" content="{{ isset($description) ? $description : trans('texts.app_description') }}" />
<link href="{{ asset('favicon.png') }}" rel="shortcut icon">
<link href="{{ asset('favicon-v2.png') }}" rel="shortcut icon">
@endif
<!-- Source: https://github.com/hillelcoren/invoice-ninja -->

View File

@ -3,147 +3,66 @@
@section('head')
@parent
<!--
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
-->
@if ($accountGateway->getPublishableStripeKey())
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey('{{ $accountGateway->getPublishableStripeKey() }}');
$(function() {
$('.payment-form').submit(function(event) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
function stripeResponseHandler(status, response) {
var $form = $('.payment-form');
if (response.error) {
// Show the errors on the form
var error = response.error.message;
$form.find('button').prop('disabled', false);
$('#js-error-message').html(error).fadeIn();
} else {
// response contains id and card, which contains additional card details
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken"/>').val(token));
// and submit
$form.get(0).submit();
}
};
</script>
@else
<script type="text/javascript">
$(function() {
$('.payment-form').submit(function(event) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
return true;
});
});
</script>
@endif
@stop
@section('content')
<style type="text/css">
body {
background-color: #f8f8f8;
color: #1b1a1a;
}
.panel-body {
padding-bottom: 50px;
}
.container input[type=text],
.container input[type=email],
.container select {
font-weight: 300;
font-family: 'Roboto', sans-serif;
width: 100%;
padding: 11px;
color: #8c8c8c;
background: #f9f9f9;
border: 1px solid #ebe7e7;
border-radius: 3px;
font-size: 16px;
min-height: 42px !important;
font-weight: 400;
}
div.col-md-3,
div.col-md-5,
div.col-md-6,
div.col-md-7,
div.col-md-9,
div.col-md-12 {
margin: 6px 0 6px 0;
}
span.dropdown-toggle {
border-color: #ebe7e7;
}
.dropdown-toggle {
margin: 0px !important;
}
.container input[placeholder],
.container select[placeholder] {
color: #444444;
}
div.row {
padding-top: 8px;
}
header {
margin: 0px !important
}
@media screen and (min-width: 700px) {
header {
margin: 20px 0 75px;
float: left;
}
.panel-body {
padding-left: 150px;
padding-right: 150px;
}
}
h2 {
font-weight: 300;
font-size: 30px;
color: #2e2b2b;
line-height: 1;
}
h3 {
font-weight: 900;
margin-top: 10px;
font-size: 15px;
}
h3 .help {
font-style: italic;
font-weight: normal;
color: #888888;
}
header h3 {
text-transform: uppercase;
}
header h3 span {
display: inline-block;
margin-left: 8px;
}
header h3 em {
font-style: normal;
color: #eb8039;
}
.secure {
text-align: right;
float: right;
background: url({{ asset('/images/icon-shield.png') }}) right 22px no-repeat;
padding: 17px 55px 10px 0;
}
.secure h3 {
color: #36b855;
font-size: 30px;
margin-bottom: 8px;
margin-top: 0px;
}
.secure div {
color: #acacac;
font-size: 15px;
font-weight: 900;
text-transform: uppercase;
}
</style>
@include('payments.payment_css')
{!! Former::vertical_open($url)
->autocomplete('on')
->addClass('payment-form')
->rules(array(
'first_name' => 'required',
'last_name' => 'required',
@ -172,6 +91,8 @@ header h3 em {
<div class="container">
<p>&nbsp;</p>
<div id="js-error-message" style="display:none" class="alert alert-danger"></div>
<div class="panel panel-default">
<div class="panel-body">
@ -279,14 +200,14 @@ header h3 em {
<h3>{{ trans('texts.billing_method') }}</h3>
<div class="row">
<div class="col-md-9">
{!! Former::text($gateway->isGateway(GATEWAY_STRIPE) ? 'card_number' : 'card_number')
{!! Former::text($accountGateway->getPublishableStripeKey() ? '' : 'card_number')
->placeholder(trans('texts.card_number'))
->autocomplete('cc-number')
->data_stripe('number')
->label('') !!}
</div>
<div class="col-md-3">
{!! Former::text($gateway->isGateway(GATEWAY_STRIPE) ? 'cvv' : 'cvv')
{!! Former::text($accountGateway->getPublishableStripeKey() ? '' : 'cvv')
->placeholder(trans('texts.cvv'))
->autocomplete('off')
->data_stripe('cvc')
@ -295,7 +216,7 @@ header h3 em {
</div>
<div class="row">
<div class="col-md-6">
{!! Former::select($gateway->isGateway(GATEWAY_STRIPE) ? 'expiration_month' : 'expiration_month')
{!! Former::select($accountGateway->getPublishableStripeKey() ? '' : 'expiration_month')
->autocomplete('cc-exp-month')
->data_stripe('exp-month')
->placeholder(trans('texts.expiration_month'))
@ -314,7 +235,7 @@ header h3 em {
!!}
</div>
<div class="col-md-6">
{!! Former::select($gateway->isGateway(GATEWAY_STRIPE) ? 'expiration_year' : 'expiration_year')
{!! Former::select($accountGateway->getPublishableStripeKey() ? '' : 'expiration_year')
->autocomplete('cc-exp-year')
->data_stripe('exp-year')
->placeholder(trans('texts.expiration_year'))
@ -336,15 +257,15 @@ header h3 em {
<div class="row" style="padding-top:18px">
<div class="col-md-5">
@if ($client && $account->showTokenCheckbox())
@if ($client && $account->showTokenCheckbox())
<input id="token_billing" type="checkbox" name="token_billing" {{ $account->selectTokenCheckbox() ? 'CHECKED' : '' }} value="1" style="margin-left:0px; vertical-align:top">
<label for="token_billing" class="checkbox" style="display: inline;">{{ trans('texts.token_billing') }}</label>
<span class="help-block" style="font-size:15px">{!! trans('texts.token_billing_secure', ['stripe_link' => link_to('https://stripe.com/', 'Stripe.com', ['target' => '_blank'])]) !!}</span>
@endif
@endif
</div>
<div class="col-md-7">
@if (isset($acceptedCreditCardTypes))
<div class="col-md-7">
@if (isset($acceptedCreditCardTypes))
<div class="pull-right">
@foreach ($acceptedCreditCardTypes as $card)
<img src="{{ $card['source'] }}" alt="{{ $card['alt'] }}" style="width: 70px; display: inline; margin-right: 6px;"/>

View File

@ -0,0 +1,130 @@
<style type="text/css">
body {
background-color: #f8f8f8;
color: #1b1a1a;
}
.panel-body {
padding-bottom: 50px;
}
.container input[type=text],
.container input[type=email],
.container select {
font-weight: 300;
font-family: 'Roboto', sans-serif;
width: 100%;
padding: 11px;
color: #8c8c8c;
background: #f9f9f9;
border: 1px solid #ebe7e7;
border-radius: 3px;
font-size: 16px;
min-height: 42px !important;
font-weight: 400;
}
div.col-md-3,
div.col-md-5,
div.col-md-6,
div.col-md-7,
div.col-md-9,
div.col-md-12 {
margin: 6px 0 6px 0;
}
span.dropdown-toggle {
border-color: #ebe7e7;
}
.dropdown-toggle {
margin: 0px !important;
}
.container input[placeholder],
.container select[placeholder] {
color: #444444;
}
div.row {
padding-top: 8px;
}
header {
margin: 0px !important
}
@media screen and (min-width: 700px) {
header {
margin: 20px 0 75px;
float: left;
}
.panel-body {
padding-left: 150px;
padding-right: 150px;
}
}
h2 {
font-weight: 300;
font-size: 30px;
color: #2e2b2b;
line-height: 1;
}
h3 {
font-weight: 900;
margin-top: 10px;
font-size: 15px;
}
h3 .help {
font-style: italic;
font-weight: normal;
color: #888888;
}
header h3 {
text-transform: uppercase;
}
header h3 span {
display: inline-block;
margin-left: 8px;
}
header h3 em {
font-style: normal;
color: #eb8039;
}
.secure {
text-align: right;
float: right;
background: url({{ asset('/images/icon-shield.png') }}) right 22px no-repeat;
padding: 17px 55px 10px 0;
}
.secure h3 {
color: #36b855;
font-size: 30px;
margin-bottom: 8px;
margin-top: 0px;
}
.secure div {
color: #acacac;
font-size: 15px;
font-weight: 900;
text-transform: uppercase;
}
</style>

View File

@ -1,4 +1,4 @@
<?php //[STAMP] f6d69edc5937bdfc3f7eeb6538ccd9ba
<?php //[STAMP] fd572cb1f679911978b9f48a842ed64b
namespace _generated;
// This class was automatically generated by build task
@ -17,17 +17,6 @@ trait AcceptanceTesterActions
abstract protected function getScenario();
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Print out latest Selenium Logs in debug mode
* @see \Codeception\Module\WebDriver::debugWebDriverLogs()
*/
public function debugWebDriverLogs() {
return $this->getScenario()->runStep(new \Codeception\Step\Action('debugWebDriverLogs', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -260,6 +249,7 @@ trait AcceptanceTesterActions
* $I->amOnPage('/');
* // opens /register page
* $I->amOnPage('/register');
* ?>
* ```
*
* @param $page
@ -273,31 +263,16 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string (case insensitive).
*
* You can specify a specific HTML element (via CSS or XPath) as the second
* parameter to only search within that element.
* Checks that the current page contains the given string.
* Specify a locator as the second parameter to match a specific region.
*
* ``` php
* <?php
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up', 'h1'); // I can suppose it's a signup page
* $I->see('Sign Up', '//body/h1'); // with XPath
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up','h1'); // I can suppose it's a signup page
* $I->see('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->see('strong')` will return true for strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will *not* be true for strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -310,31 +285,16 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string (case insensitive).
*
* You can specify a specific HTML element (via CSS or XPath) as the second
* parameter to only search within that element.
* Checks that the current page contains the given string.
* Specify a locator as the second parameter to match a specific region.
*
* ``` php
* <?php
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up', 'h1'); // I can suppose it's a signup page
* $I->see('Sign Up', '//body/h1'); // with XPath
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up','h1'); // I can suppose it's a signup page
* $I->see('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->see('strong')` will return true for strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will *not* be true for strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -348,29 +308,16 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page doesn't contain the text specified (case insensitive).
* Checks that the current page doesn't contain the text specified.
* Give a locator as the second parameter to match a specific region.
*
* ```php
* <?php
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->dontSee('strong')` will fail on strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will ignore strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -383,29 +330,16 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page doesn't contain the text specified (case insensitive).
* Checks that the current page doesn't contain the text specified.
* Give a locator as the second parameter to match a specific region.
*
* ```php
* <?php
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->dontSee('strong')` will fail on strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will ignore strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -416,80 +350,6 @@ trait AcceptanceTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ``` php
* <?php
* $I->seeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\WebDriver::seeInSource()
*/
public function canSeeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ``` php
* <?php
* $I->seeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* @see \Codeception\Module\WebDriver::seeInSource()
*/
public function seeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ```php
* <?php
* $I->dontSeeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\WebDriver::dontSeeInSource()
*/
public function cantSeeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ```php
* <?php
* $I->dontSeeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* @see \Codeception\Module\WebDriver::dontSeeInSource()
*/
public function dontSeeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -1565,28 +1425,7 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Grabs either the text content, or attribute values, of nodes
* matched by $cssOrXpath and returns them as an array.
*
* ```html
* <a href="#first">First</a>
* <a href="#second">Second</a>
* <a href="#third">Third</a>
* ```
*
* ```php
* <?php
* // would return ['First', 'Second', 'Third']
* $aLinkText = $I->grabMultiple('a');
*
* // would return ['#first', '#second', '#third']
* $aLinks = $I->grabMultiple('a', 'href');
* ?>
* ```
*
* @param $cssOrXpath
* @param $attribute
* @return string[]
*
* @see \Codeception\Module\WebDriver::grabMultiple()
*/
public function grabMultiple($cssOrXpath, $attribute = null) {
@ -1801,27 +1640,6 @@ trait AcceptanceTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
*
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\WebDriver::seeNumberOfElementsInDOM()
*/
public function canSeeNumberOfElementsInDOM($selector, $expected) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElementsInDOM', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
*
* @see \Codeception\Module\WebDriver::seeNumberOfElementsInDOM()
*/
public function seeNumberOfElementsInDOM($selector, $expected) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberOfElementsInDOM', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -2139,13 +1957,13 @@ trait AcceptanceTesterActions
* ```
* Note that "2" will be the submitted value for the "plan" field, as it is
* the selected option.
*
*
* Also note that this differs from PhpBrowser, in that
* ```'user' => [ 'login' => 'Davert' ]``` is not supported at the moment.
* Named array keys *must* be included in the name as above.
*
*
* Pair this with seeInFormFields for quick testing magic.
*
*
* ``` php
* <?php
* $form = [
@ -2188,20 +2006,20 @@ trait AcceptanceTesterActions
*
* Mixing string and boolean values for a checkbox's value is not supported
* and may produce unexpected results.
*
* Field names ending in "[]" must be passed without the trailing square
*
* Field names ending in "[]" must be passed without the trailing square
* bracket characters, and must contain an array for its value. This allows
* submitting multiple values with the same name, consider:
*
*
* ```php
* $I->submitForm('#my-form', [
* 'field[]' => 'value',
* 'field[]' => 'another value', // 'field[]' is already a defined key
* ]);
* ```
*
*
* The solution is to pass an array value:
*
*
* ```php
* // this way both values are submitted
* $I->submitForm('#my-form', [
@ -2645,7 +2463,34 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* @param string $name
* Saves current cookies into named snapshot in order to restore them in other tests
* This is useful to save session state between tests.
* For example, if user needs log in to site for each test this scenario can be executed once
* while other tests can just restore saved cookies.
*
* ``` php
* <?php
* // inside AcceptanceTester class:
*
* public function login()
* {
* // if snapshot exists - skipping login
* if ($I->loadSessionSnapshot('login')) return;
*
* // logging in
* $I->amOnPage('/login');
* $I->fillField('name', 'jon');
* $I->fillField('password', '123345');
* $I->click('Login');
*
* // saving snapshot
* $I->saveSessionSnapshot('login');
* }
* ?>
* ```
*
* @param $name
* @return mixed
* @see \Codeception\Module\WebDriver::saveSessionSnapshot()
*/
public function saveSessionSnapshot($name) {
@ -2656,8 +2501,11 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* @param string $name
* @return bool
* Loads cookies from saved snapshot.
*
* @param $name
* @see saveSessionSnapshot
* @return mixed
* @see \Codeception\Module\WebDriver::loadSessionSnapshot()
*/
public function loadSessionSnapshot($name) {
@ -2668,7 +2516,7 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Inserts an SQL record into a database. This record will be erased after the test.
* Inserts SQL record into database. This record will be erased after the test.
*
* ``` php
* <?php
@ -2690,7 +2538,7 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Asserts that a row with the given column values exists.
* Checks if a row with given column values exists.
* Provide table name and column values.
*
* Example:
@ -2718,7 +2566,7 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Asserts that a row with the given column values exists.
* Checks if a row with given column values exists.
* Provide table name and column values.
*
* Example:
@ -2747,7 +2595,7 @@ trait AcceptanceTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Asserts that the given number of records were found in the database.
* Asserts that found number of records in database
*
* ``` php
* <?php
@ -2755,19 +2603,19 @@ trait AcceptanceTesterActions
* ?>
* ```
*
* @param int $expectedNumber Expected number
* @param int $num Expected number
* @param string $table Table name
* @param array $criteria Search criteria [Optional]
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Db::seeNumRecords()
*/
public function canSeeNumRecords($expectedNumber, $table, $criteria = null) {
public function canSeeNumRecords($num, $table, $criteria = null) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumRecords', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Asserts that the given number of records were found in the database.
* Asserts that found number of records in database
*
* ``` php
* <?php
@ -2775,12 +2623,12 @@ trait AcceptanceTesterActions
* ?>
* ```
*
* @param int $expectedNumber Expected number
* @param int $num Expected number
* @param string $table Table name
* @param array $criteria Search criteria [Optional]
* @see \Codeception\Module\Db::seeNumRecords()
*/
public function seeNumRecords($expectedNumber, $table, $criteria = null) {
public function seeNumRecords($num, $table, $criteria = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumRecords', func_get_args()));
}
@ -2790,7 +2638,7 @@ trait AcceptanceTesterActions
*
* Effect is opposite to ->seeInDatabase
*
* Asserts that there is no record with the given column values in a database.
* Checks if there is no record with such column values in database.
* Provide table name and column values.
*
* Example:
@ -2820,7 +2668,7 @@ trait AcceptanceTesterActions
*
* Effect is opposite to ->seeInDatabase
*
* Asserts that there is no record with the given column values in a database.
* Checks if there is no record with such column values in database.
* Provide table name and column values.
*
* Example:

View File

@ -1,4 +1,4 @@
<?php //[STAMP] a0d5cd84d7074a41bde1bd3fc123f1cf
<?php //[STAMP] 3a5564865956327f909936a09aa15a20
namespace _generated;
// This class was automatically generated by build task
@ -164,6 +164,7 @@ trait FunctionalTesterActions
* $I->amOnPage('/');
* // opens /register page
* $I->amOnPage('/register');
* ?>
* ```
*
* @param $page
@ -216,31 +217,16 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string (case insensitive).
*
* You can specify a specific HTML element (via CSS or XPath) as the second
* parameter to only search within that element.
* Checks that the current page contains the given string.
* Specify a locator as the second parameter to match a specific region.
*
* ``` php
* <?php
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up', 'h1'); // I can suppose it's a signup page
* $I->see('Sign Up', '//body/h1'); // with XPath
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up','h1'); // I can suppose it's a signup page
* $I->see('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->see('strong')` will return true for strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will *not* be true for strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -253,31 +239,16 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string (case insensitive).
*
* You can specify a specific HTML element (via CSS or XPath) as the second
* parameter to only search within that element.
* Checks that the current page contains the given string.
* Specify a locator as the second parameter to match a specific region.
*
* ``` php
* <?php
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up', 'h1'); // I can suppose it's a signup page
* $I->see('Sign Up', '//body/h1'); // with XPath
* $I->see('Logout'); // I can suppose user is logged in
* $I->see('Sign Up','h1'); // I can suppose it's a signup page
* $I->see('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->see('strong')` will return true for strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will *not* be true for strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -291,29 +262,16 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page doesn't contain the text specified (case insensitive).
* Checks that the current page doesn't contain the text specified.
* Give a locator as the second parameter to match a specific region.
*
* ```php
* <?php
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->dontSee('strong')` will fail on strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will ignore strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -326,29 +284,16 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page doesn't contain the text specified (case insensitive).
* Checks that the current page doesn't contain the text specified.
* Give a locator as the second parameter to match a specific region.
*
* ```php
* <?php
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* $I->dontSee('Login'); // I can suppose user is already logged in
* $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
* $I->dontSee('Sign Up','//body/h1'); // with XPath
* ?>
* ```
*
* Note that the search is done after stripping all HTML tags from the body,
* so `$I->dontSee('strong')` will fail on strings like:
*
* - `<p>I am Stronger than thou</p>`
* - `<script>document.createElement('strong');</script>`
*
* But will ignore strings like:
*
* - `<strong>Home</strong>`
* - `<div class="strong">Home</strong>`
* - `<!-- strong -->`
*
* For checking the raw source code, use `seeInSource()`.
*
* @param $text
* @param null $selector
@ -359,80 +304,6 @@ trait FunctionalTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ``` php
* <?php
* $I->seeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Lib\InnerBrowser::seeInSource()
*/
public function canSeeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ``` php
* <?php
* $I->seeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* @see \Codeception\Lib\InnerBrowser::seeInSource()
*/
public function seeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ```php
* <?php
* $I->dontSeeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Lib\InnerBrowser::dontSeeInSource()
*/
public function cantSeeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that the current page contains the given string in its
* raw source code.
*
* ```php
* <?php
* $I->dontSeeInSource('<h1>Green eggs &amp; ham</h1>');
* ```
*
* @param $raw
* @see \Codeception\Lib\InnerBrowser::dontSeeInSource()
*/
public function dontSeeInSource($raw) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInSource', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -1205,25 +1076,13 @@ trait FunctionalTesterActions
* Submits the given form on the page, optionally with the given form
* values. Give the form fields values as an array.
*
* Although this function can be used as a short-hand version of
* `fillField()`, `selectOption()`, `click()` etc. it has some important
* differences:
*
* * Only field *names* may be used, not CSS/XPath selectors nor field labels
* * If a field is sent to this function that does *not* exist on the page,
* it will silently be added to the HTTP request. This is helpful for testing
* some types of forms, but be aware that you will *not* get an exception
* like you would if you called `fillField()` or `selectOption()` with
* a missing field.
*
* Fields that are not provided will be filled by their values from the page,
* or from any previous calls to `fillField()`, `selectOption()` etc.
* Skipped fields will be filled by their values from the page.
* You don't need to click the 'Submit' button afterwards.
* This command itself triggers the request to form's action.
*
* You can optionally specify which button's value to include
* in the request with the last parameter (as an alternative to
* explicitly setting its value in the second parameter), as
* You can optionally specify what button's value to include
* in the request with the last parameter as an alternative to
* explicitly setting its value in the second parameter, as
* button values are not otherwise included in the request.
*
* Examples:
@ -1297,8 +1156,7 @@ trait FunctionalTesterActions
* );
* ```
*
* This function works well when paired with `seeInFormFields()`
* for quickly testing CRUD interfaces and form validation logic.
* Pair this with seeInFormFields for quick testing magic.
*
* ``` php
* <?php
@ -1308,14 +1166,15 @@ trait FunctionalTesterActions
* 'checkbox1' => true,
* // ...
* ];
* $I->submitForm('#my-form', $form, 'submitButton');
* $I->submitForm('//form[@id=my-form]', $form, 'submitButton');
* // $I->amOnPage('/path/to/form-page') may be needed
* $I->seeInFormFields('#my-form', $form);
* $I->seeInFormFields('//form[@id=my-form]', $form);
* ?>
* ```
*
* Parameter values can be set to arrays for multiple input fields
* of the same name, or multi-select combo boxes. For checkboxes,
* you can use either the string value or boolean `true`/`false` which will
* either the string value can be used, or boolean values which will
* be replaced by the checkbox's value in the DOM.
*
* ``` php
@ -1324,7 +1183,7 @@ trait FunctionalTesterActions
* 'field1' => 'value',
* 'checkbox' => [
* 'value of first checkbox',
* 'value of second checkbox',
* 'value of second checkbox,
* ],
* 'otherCheckboxes' => [
* true,
@ -1336,29 +1195,27 @@ trait FunctionalTesterActions
* 'second option value'
* ]
* ]);
* ?>
* ```
*
* Mixing string and boolean values for a checkbox's value is not supported
* and may produce unexpected results.
*
* Field names ending in `[]` must be passed without the trailing square
* Field names ending in "[]" must be passed without the trailing square
* bracket characters, and must contain an array for its value. This allows
* submitting multiple values with the same name, consider:
*
* ```php
* <?php
* // This will NOT work correctly
* $I->submitForm('#my-form', [
* 'field[]' => 'value',
* 'field[]' => 'another value', // 'field[]' is already a defined key
* 'field[]' => 'another value', // 'field[]' is already a defined key
* ]);
* ```
*
* The solution is to pass an array value:
*
* ```php
* <?php
* // This way both values are submitted
* // this way both values are submitted
* $I->submitForm('#my-form', [
* 'field' => [
* 'value',
@ -1609,28 +1466,7 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Grabs either the text content, or attribute values, of nodes
* matched by $cssOrXpath and returns them as an array.
*
* ```html
* <a href="#first">First</a>
* <a href="#second">Second</a>
* <a href="#third">Third</a>
* ```
*
* ```php
* <?php
* // would return ['First', 'Second', 'Third']
* $aLinkText = $I->grabMultiple('a');
*
* // would return ['#first', '#second', '#third']
* $aLinks = $I->grabMultiple('a', 'href');
* ?>
* ```
*
* @param $cssOrXpath
* @param $attribute
* @return string[]
*
* @see \Codeception\Lib\InnerBrowser::grabMultiple()
*/
public function grabMultiple($cssOrXpath, $attribute = null) {
@ -2136,43 +1972,6 @@ trait FunctionalTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Switch to iframe or frame on the page.
*
* Example:
* ``` html
* <iframe name="another_frame" src="http://example.com">
* ```
*
* ``` php
* <?php
* # switch to iframe
* $I->switchToIframe("another_frame");
* ```
*
* @param string $name
* @see \Codeception\Lib\InnerBrowser::switchToIframe()
*/
public function switchToIframe($name) {
return $this->getScenario()->runStep(new \Codeception\Step\Action('switchToIframe', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Moves back in history.
*
* @param int $numberOfSteps (default value 1)
* @see \Codeception\Lib\InnerBrowser::moveBack()
*/
public function moveBack($numberOfSteps = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Action('moveBack', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -2231,122 +2030,6 @@ trait FunctionalTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Disable events for the next requests.
*
* ``` php
* <?php
* $I->disableEvents();
* ?>
* ```
* @see \Codeception\Module\Laravel5::disableEvents()
*/
public function disableEvents() {
return $this->getScenario()->runStep(new \Codeception\Step\Action('disableEvents', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Enable events for the next requests.
*
* ``` php
* <?php
* $I->enableEvents();
* ?>
* ```
* @see \Codeception\Module\Laravel5::enableEvents()
*/
public function enableEvents() {
return $this->getScenario()->runStep(new \Codeception\Step\Action('enableEvents', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Make sure events fired during the test.
*
* ``` php
* <?php
* $I->seeEventTriggered('App\MyEvent');
* $I->seeEventTriggered(new App\Events\MyEvent());
* $I->seeEventTriggered('App\MyEvent', 'App\MyOtherEvent');
* $I->seeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']);
* ?>
* ```
* @param $events
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::seeEventTriggered()
*/
public function canSeeEventTriggered($events) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeEventTriggered', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Make sure events fired during the test.
*
* ``` php
* <?php
* $I->seeEventTriggered('App\MyEvent');
* $I->seeEventTriggered(new App\Events\MyEvent());
* $I->seeEventTriggered('App\MyEvent', 'App\MyOtherEvent');
* $I->seeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']);
* ?>
* ```
* @param $events
* @see \Codeception\Module\Laravel5::seeEventTriggered()
*/
public function seeEventTriggered($events) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeEventTriggered', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Make sure events did not fire during the test.
*
* ``` php
* <?php
* $I->dontSeeEventTriggered('App\MyEvent');
* $I->dontSeeEventTriggered(new App\Events\MyEvent());
* $I->dontSeeEventTriggered('App\MyEvent', 'App\MyOtherEvent');
* $I->dontSeeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']);
* ?>
* ```
* @param $events
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::dontSeeEventTriggered()
*/
public function cantSeeEventTriggered($events) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeEventTriggered', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Make sure events did not fire during the test.
*
* ``` php
* <?php
* $I->dontSeeEventTriggered('App\MyEvent');
* $I->dontSeeEventTriggered(new App\Events\MyEvent());
* $I->dontSeeEventTriggered('App\MyEvent', 'App\MyOtherEvent');
* $I->dontSeeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']);
* ?>
* ```
* @param $events
* @see \Codeception\Module\Laravel5::dontSeeEventTriggered()
*/
public function dontSeeEventTriggered($events) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeEventTriggered', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -2367,41 +2050,6 @@ trait FunctionalTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that current url matches route
*
* ``` php
* <?php
* $I->seeCurrentRouteIs('posts.index');
* ?>
* ```
* @param $routeName
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::seeCurrentRouteIs()
*/
public function canSeeCurrentRouteIs($routeName) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentRouteIs', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that current url matches route
*
* ``` php
* <?php
* $I->seeCurrentRouteIs('posts.index');
* ?>
* ```
* @param $routeName
* @see \Codeception\Module\Laravel5::seeCurrentRouteIs()
*/
public function seeCurrentRouteIs($routeName) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentRouteIs', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -2422,6 +2070,43 @@ trait FunctionalTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that current url matches route
*
* ``` php
* <?php
* $I->seeCurrentRouteIs('posts.index');
* ?>
* ```
* @param $route
* @param array $params
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::seeCurrentRouteIs()
*/
public function canSeeCurrentRouteIs($route, $params = null) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentRouteIs', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that current url matches route
*
* ``` php
* <?php
* $I->seeCurrentRouteIs('posts.index');
* ?>
* ```
* @param $route
* @param array $params
* @see \Codeception\Module\Laravel5::seeCurrentRouteIs()
*/
public function seeCurrentRouteIs($route, $params = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentRouteIs', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
@ -2434,10 +2119,11 @@ trait FunctionalTesterActions
* ```
*
* @param $action
* @param array $params
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::seeCurrentActionIs()
*/
public function canSeeCurrentActionIs($action) {
public function canSeeCurrentActionIs($action, $params = null) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentActionIs', func_get_args()));
}
/**
@ -2452,9 +2138,10 @@ trait FunctionalTesterActions
* ```
*
* @param $action
* @param array $params
* @see \Codeception\Module\Laravel5::seeCurrentActionIs()
*/
public function seeCurrentActionIs($action) {
public function seeCurrentActionIs($action, $params = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentActionIs', func_get_args()));
}
@ -2472,7 +2159,7 @@ trait FunctionalTesterActions
* ```
*
* @param string|array $key
* @param mixed|null $value
* @param mixed $value
* @return void
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::seeInSession()
@ -2493,7 +2180,7 @@ trait FunctionalTesterActions
* ```
*
* @param string|array $key
* @param mixed|null $value
* @param mixed $value
* @return void
* @see \Codeception\Module\Laravel5::seeInSession()
*/
@ -2580,56 +2267,19 @@ trait FunctionalTesterActions
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Assert that there are no form errors bound to the View.
*
* ``` php
* <?php
* $I->dontSeeFormErrors();
* ?>
* ```
*
* @return bool
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::dontSeeFormErrors()
*/
public function cantSeeFormErrors() {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFormErrors', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Assert that there are no form errors bound to the View.
*
* ``` php
* <?php
* $I->dontSeeFormErrors();
* ?>
* ```
*
* @return bool
* @see \Codeception\Module\Laravel5::dontSeeFormErrors()
*/
public function dontSeeFormErrors() {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeFormErrors', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Assert that specific form error messages are set in the view.
*
* This method calls `seeFormErrorMessage` for each entry in the `$bindings` array.
* Useful for validation messages e.g.
* return `Redirect::to('register')->withErrors($validator);`
*
* Example of Usage
*
* ``` php
* <?php
* $I->seeFormErrorMessages([
* 'username' => 'Invalid Username',
* 'password' => null,
* ]);
* $I->seeFormErrorMessages(array('username'=>'Invalid Username'));
* ?>
* ```
* @param array $bindings
@ -2644,14 +2294,14 @@ trait FunctionalTesterActions
*
* Assert that specific form error messages are set in the view.
*
* This method calls `seeFormErrorMessage` for each entry in the `$bindings` array.
* Useful for validation messages e.g.
* return `Redirect::to('register')->withErrors($validator);`
*
* Example of Usage
*
* ``` php
* <?php
* $I->seeFormErrorMessages([
* 'username' => 'Invalid Username',
* 'password' => null,
* ]);
* $I->seeFormErrorMessages(array('username'=>'Invalid Username'));
* ?>
* ```
* @param array $bindings
@ -2665,50 +2315,48 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Assert that a specific form error message is set in the view.
* Assert that specific form error message is set in the view.
*
* If you want to assert that there is a form error message for a specific key
* but don't care about the actual error message you can omit `$expectedErrorMessage`.
* Useful for validation messages and generally messages array
* e.g.
* return `Redirect::to('register')->withErrors($validator);`
*
* If you do pass `$expectedErrorMessage`, this method checks if the actual error message for a key
* contains `$expectedErrorMessage`.
* Example of Usage
*
* ``` php
* <?php
* $I->seeFormErrorMessage('username');
* $I->seeFormErrorMessage('username', 'Invalid Username');
* ?>
* ```
* @param string $key
* @param string|null $expectedErrorMessage
* @param string $errorMessage
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::seeFormErrorMessage()
*/
public function canSeeFormErrorMessage($key, $expectedErrorMessage = null) {
public function canSeeFormErrorMessage($key, $errorMessage) {
return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFormErrorMessage', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Assert that a specific form error message is set in the view.
* Assert that specific form error message is set in the view.
*
* If you want to assert that there is a form error message for a specific key
* but don't care about the actual error message you can omit `$expectedErrorMessage`.
* Useful for validation messages and generally messages array
* e.g.
* return `Redirect::to('register')->withErrors($validator);`
*
* If you do pass `$expectedErrorMessage`, this method checks if the actual error message for a key
* contains `$expectedErrorMessage`.
* Example of Usage
*
* ``` php
* <?php
* $I->seeFormErrorMessage('username');
* $I->seeFormErrorMessage('username', 'Invalid Username');
* ?>
* ```
* @param string $key
* @param string|null $expectedErrorMessage
* @param string $errorMessage
* @see \Codeception\Module\Laravel5::seeFormErrorMessage()
*/
public function seeFormErrorMessage($key, $expectedErrorMessage = null) {
public function seeFormErrorMessage($key, $errorMessage) {
return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFormErrorMessage', func_get_args()));
}
@ -2720,19 +2368,8 @@ trait FunctionalTesterActions
* Takes either an object that implements the User interface or
* an array of credentials.
*
* ``` php
* <?php
* // provide array of credentials
* $I->amLoggedAs(['username' => 'jane@example.com', 'password' => 'password']);
*
* // provide User object
* $I->amLoggesAs( new User );
*
* // can be verified with $I->seeAuthentication();
* ?>
* ```
* @param \Illuminate\Contracts\Auth\User|array $user
* @param string|null $driver 'eloquent', 'database', or custom driver
* @param string $driver
* @return void
* @see \Codeception\Module\Laravel5::amLoggedAs()
*/
@ -2744,7 +2381,7 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Logout user.
* Logs user out
* @see \Codeception\Module\Laravel5::logout()
*/
public function logout() {
@ -2755,7 +2392,7 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that a user is authenticated
* Checks that user is authenticated
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Laravel5::seeAuthentication()
*/
@ -2765,7 +2402,7 @@ trait FunctionalTesterActions
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that a user is authenticated
* Checks that user is authenticated
* @see \Codeception\Module\Laravel5::seeAuthentication()
*/
public function seeAuthentication() {
@ -2800,6 +2437,7 @@ trait FunctionalTesterActions
* Return an instance of a class from the IoC Container.
* (http://laravel.com/docs/ioc)
*
* Example
* ``` php
* <?php
* // In Laravel
@ -2948,88 +2586,4 @@ trait FunctionalTesterActions
public function grabRecord($tableName, $attributes = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Action('grabRecord', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Use Laravel's model factory to create a model.
* Can only be used with Laravel 5.1 and later.
*
* ``` php
* <?php
* $I->haveModel('App\User');
* $I->haveModel('App\User', ['name' => 'John Doe']);
* $I->haveModel('App\User', [], 'admin');
* $I->haveModel('App\User', [], 'admin', 3);
* ?>
* ```
*
* @see http://laravel.com/docs/5.1/testing#model-factories
* @param string $model
* @param array $attributes
* @param string $name
* @param int $times
* @return mixed
* @see \Codeception\Module\Laravel5::haveModel()
*/
public function haveModel($model, $attributes = null, $name = null, $times = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Action('haveModel', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Use Laravel's model factory to create a model.
* Can only be used with Laravel 5.1 and later.
*
* ``` php
* <?php
* $I->createModel('App\User');
* $I->createModel('App\User', ['name' => 'John Doe']);
* $I->createModel('App\User', [], 'admin');
* $I->createModel('App\User', [], 'admin', 3);
* ?>
* ```
*
* @see http://laravel.com/docs/5.1/testing#model-factories
* @param string $model
* @param array $attributes
* @param string $name
* @param int $times
* @return mixed
* @see \Codeception\Module\Laravel5::createModel()
*/
public function createModel($model, $attributes = null, $name = null, $times = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Action('createModel', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Use Laravel's model factory to make a model.
* Can only be used with Laravel 5.1 and later.
*
* ``` php
* <?php
* $I->makeModel('App\User');
* $I->makeModel('App\User', ['name' => 'John Doe']);
* $I->makeModel('App\User', [], 'admin');
* $I->makeModel('App\User', [], 'admin', 3);
* ?>
* ```
*
* @see http://laravel.com/docs/5.1/testing#model-factories
* @param string $model
* @param array $attributes
* @param string $name
* @param int $times
* @return mixed
* @see \Codeception\Module\Laravel5::makeModel()
*/
public function makeModel($model, $attributes = null, $name = null, $times = null) {
return $this->getScenario()->runStep(new \Codeception\Step\Action('makeModel', func_get_args()));
}
}

View File

@ -1,4 +1,4 @@
<?php //[STAMP] 9d680d4d116f13b46f4a15d3ff55e20a
<?php //[STAMP] 411f8e49789d4aff7d24b72665b5df9f
namespace _generated;
// This class was automatically generated by build task

View File

@ -0,0 +1,116 @@
<?php
use Codeception\Util\Fixtures;
use Faker\Factory;
use Codeception\Util\Debug;
class APICest
{
private $faker;
private $token;
public function _before(AcceptanceTester $I)
{
$this->faker = Factory::create();
Debug::debug('Create/get token');
$data = new stdClass;
$data->email = Fixtures::get('username');
$data->password = Fixtures::get('password');
$data->api_secret = Fixtures::get('api_secret');
$data->token_name = 'iOS Token';
$response = $this->sendRequest('login', $data);
$userAccounts = $response->data;
PHPUnit_Framework_Assert::assertGreaterThan(0, count($userAccounts));
$userAccount = $userAccounts[0];
$this->token = $userAccount->token;
Debug::debug("Token: {$this->token}");
}
public function testAPI(AcceptanceTester $I)
{
$I->wantTo('test the API');
$data = new stdClass;
$data->contact = new stdClass;
$data->contact->email = $this->faker->safeEmail;
$clientId = $this->createEntity('client', $data);
$this->listEntities('client');
$data = new stdClass;
$data->client_id = $clientId;
$data->description = $this->faker->realText(100);
$this->createEntity('task', $data);
$this->listEntities('task');
$lineItem = new stdClass;
$lineItem->qty = $this->faker->numberBetween(1, 10);
$lineItem->cost = $this->faker->numberBetween(1, 10);
$data = new stdClass;
$data->client_id = $clientId;
$data->invoice_items = [
$lineItem
];
$invoiceId = $this->createEntity('invoice', $data);
$this->listEntities('invoice');
$data = new stdClass;
$data->invoice_id = $invoiceId;
$data->amount = 1;
$this->createEntity('payment', $data);
$this->listEntities('payment');
$this->listEntities('account');
}
private function createEntity($entityType, $data)
{
Debug::debug("Create {$entityType}");
$response = $this->sendRequest("{$entityType}s", $data);
$entityId = $response->data->id;
PHPUnit_Framework_Assert::assertGreaterThan(0, $entityId);
return $entityId;
}
private function listEntities($entityType)
{
Debug::debug("List {$entityType}s");
$response = $this->sendRequest("{$entityType}s", null, 'GET');
PHPUnit_Framework_Assert::assertGreaterThan(0, count($response->data));
return $response;
}
private function sendRequest($url, $data, $type = 'POST')
{
$url = Fixtures::get('url') . '/api/v1/' . $url;
$data = json_encode($data);
$curl = curl_init();
$opts = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $type,
CURLOPT_POST => $type === 'POST' ? 1 : 0,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen($data),
'X-Ninja-Token: '. $this->token,
],
];
curl_setopt_array($curl, $opts);
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response);
}
}

View File

@ -81,6 +81,8 @@ class OnlinePaymentCest
$I->see('Successfully applied payment');
});
$I->wait(1);
// create recurring invoice and auto-bill
$I->amOnPage('/recurring_invoices/create');
$I->selectDropdown($I, $clientEmail, '.client_select .dropdown-toggle');