diff --git a/.env.example b/.env.example
index c955b9de3a71..d103500d8a51 100644
--- a/.env.example
+++ b/.env.example
@@ -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
diff --git a/app/Http/Controllers/AccountApiController.php b/app/Http/Controllers/AccountApiController.php
index 75ef6ac8a383..9c51c40dcd3c 100644
--- a/app/Http/Controllers/AccountApiController.php
+++ b/app/Http/Controllers/AccountApiController.php
@@ -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()
diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php
index 05da6eea544b..d7722136d2de 100644
--- a/app/Http/Controllers/AccountController.php
+++ b/app/Http/Controllers/AccountController.php
@@ -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 {
diff --git a/app/Http/Controllers/AccountGatewayController.php b/app/Http/Controllers/AccountGatewayController.php
index 56f8fd662375..d481e1b029d8 100644
--- a/app/Http/Controllers/AccountGatewayController.php
+++ b/app/Http/Controllers/AccountGatewayController.php
@@ -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) {
diff --git a/app/Http/Controllers/BaseAPIController.php b/app/Http/Controllers/BaseAPIController.php
index ac10d6678622..e5878e22ab55 100644
--- a/app/Http/Controllers/BaseAPIController.php
+++ b/app/Http/Controllers/BaseAPIController.php
@@ -1,12 +1,16 @@
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;
+ }
+
}
diff --git a/app/Http/Controllers/ClientApiController.php b/app/Http/Controllers/ClientApiController.php
index c4cce4d570ad..bbe0f9fde298 100644
--- a/app/Http/Controllers/ClientApiController.php
+++ b/app/Http/Controllers/ClientApiController.php
@@ -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);
}
}
diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php
index 6504d54ed90f..6080a70331f2 100644
--- a/app/Http/Controllers/ClientController.php
+++ b/app/Http/Controllers/ClientController.php
@@ -60,7 +60,7 @@ class ClientController extends BaseController
'date_created',
'last_login',
'balance',
- 'action'
+ ''
]),
));
}
diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php
index e2d5ad78c554..e08c136b5267 100644
--- a/app/Http/Controllers/CreditController.php
+++ b/app/Http/Controllers/CreditController.php
@@ -44,7 +44,7 @@ class CreditController extends BaseController
'credit_balance',
'credit_date',
'private_notes',
- 'action'
+ ''
]),
));
}
diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php
index 7573e72e7087..53c25ed5d78a 100644
--- a/app/Http/Controllers/ImportController.php
+++ b/app/Http/Controllers/ImportController.php
@@ -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 .= ' ' . 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 .= ' ' . json_encode($skip);
+ }
+ Session::flash('warning', $message);
+ } else {
+ Session::flash('message', trans('texts.imported_file'));
+ }
} catch (Exception $exception) {
Session::flash('error', $exception->getMessage());
}
diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php
index b5f92d9a0eed..a85a1b622cd2 100644
--- a/app/Http/Controllers/InvoiceApiController.php
+++ b/app/Http/Controllers/InvoiceApiController.php
@@ -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)
diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php
index ea870d0f411d..7b04edb733fe 100644
--- a/app/Http/Controllers/InvoiceController.php
+++ b/app/Http/Controllers/InvoiceController.php
@@ -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;
diff --git a/app/Http/Controllers/PaymentApiController.php b/app/Http/Controllers/PaymentApiController.php
index f23a26969fb0..b271d4c99996 100644
--- a/app/Http/Controllers/PaymentApiController.php
+++ b/app/Http/Controllers/PaymentApiController.php
@@ -1,18 +1,23 @@
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);
}
}
diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php
index 1c881384ceb0..61e8487f53c5 100644
--- a/app/Http/Controllers/PaymentController.php
+++ b/app/Http/Controllers/PaymentController.php
@@ -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();
diff --git a/app/Http/Controllers/QuoteApiController.php b/app/Http/Controllers/QuoteApiController.php
index 055f718fb179..3e3cfa580c23 100644
--- a/app/Http/Controllers/QuoteApiController.php
+++ b/app/Http/Controllers/QuoteApiController.php
@@ -1,16 +1,22 @@
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);
}
/*
diff --git a/app/Http/Controllers/TaskApiController.php b/app/Http/Controllers/TaskApiController.php
index ddbd11f7ae92..a302944d2b62 100644
--- a/app/Http/Controllers/TaskApiController.php
+++ b/app/Http/Controllers/TaskApiController.php
@@ -1,17 +1,22 @@
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);
}
}
diff --git a/app/Http/Controllers/TaskController.php b/app/Http/Controllers/TaskController.php
index 3d4ab08935fe..c2ec5f6d96ff 100644
--- a/app/Http/Controllers/TaskController.php
+++ b/app/Http/Controllers/TaskController.php
@@ -50,7 +50,7 @@ class TaskController extends BaseController
'duration',
'description',
'status',
- 'action'
+ ''
]),
));
}
diff --git a/app/Http/Middleware/StartupCheck.php b/app/Http/Middleware/StartupCheck.php
index 08b586b80fc1..5bc4d543204a 100644
--- a/app/Http/Middleware/StartupCheck.php
+++ b/app/Http/Middleware/StartupCheck.php
@@ -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());
}
diff --git a/app/Http/routes.php b/app/Http/routes.php
index f58d5269b522..eed60982811f 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -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');
diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php
index a8c74d2b64a5..4af034825d0c 100644
--- a/app/Libraries/Utils.php
+++ b/app/Libraries/Utils.php
@@ -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;
diff --git a/app/Listeners/HandleUserLoggedIn.php b/app/Listeners/HandleUserLoggedIn.php
index 5e65af0397f8..bf39d7e34e11 100644
--- a/app/Listeners/HandleUserLoggedIn.php
+++ b/app/Listeners/HandleUserLoggedIn.php
@@ -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']));
+ }
}
}
diff --git a/app/Models/Account.php b/app/Models/Account.php
index 7d9d15d992aa..0842f36434da 100644
--- a/app/Models/Account.php
+++ b/app/Models/Account.php
@@ -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();
diff --git a/app/Models/AccountGateway.php b/app/Models/AccountGateway.php
index e27a98d772bb..a4027db6ef36 100644
--- a/app/Models/AccountGateway.php
+++ b/app/Models/AccountGateway.php
@@ -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');
+ }
}
diff --git a/app/Models/Client.php b/app/Models/Client.php
index 389fad250557..9399d2d91c34 100644
--- a/app/Models/Client.php
+++ b/app/Models/Client.php
@@ -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()
{
diff --git a/app/Models/Contact.php b/app/Models/Contact.php
index 23faf964315e..a95f40bab059 100644
--- a/app/Models/Contact.php
+++ b/app/Models/Contact.php
@@ -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()
{
diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php
index 97079eb42416..ac354d15bb6d 100644
--- a/app/Models/Invoice.php
+++ b/app/Models/Invoice.php
@@ -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);
diff --git a/app/Ninja/Import/CSV/ClientTransformer.php b/app/Ninja/Import/CSV/ClientTransformer.php
new file mode 100644
index 000000000000..8a0d4ab0130b
--- /dev/null
+++ b/app/Ninja/Import/CSV/ClientTransformer.php
@@ -0,0 +1,40 @@
+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,
+ ];
+ });
+ }
+}
diff --git a/app/Ninja/Import/CSV/InvoiceTransformer.php b/app/Ninja/Import/CSV/InvoiceTransformer.php
new file mode 100644
index 000000000000..d18d4d7b1559
--- /dev/null
+++ b/app/Ninja/Import/CSV/InvoiceTransformer.php
@@ -0,0 +1,40 @@
+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,
+ ]
+ ],
+ ];
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/Ninja/Import/CSV/PaymentTransformer.php b/app/Ninja/Import/CSV/PaymentTransformer.php
new file mode 100644
index 000000000000..87936ccbc65c
--- /dev/null
+++ b/app/Ninja/Import/CSV/PaymentTransformer.php
@@ -0,0 +1,19 @@
+ $data->paid,
+ 'payment_date_sql' => isset($data->invoice_date) ? $data->invoice_date : null,
+ 'client_id' => $data->client_id,
+ 'invoice_id' => $data->invoice_id,
+ ];
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/Ninja/Repositories/CreditRepository.php b/app/Ninja/Repositories/CreditRepository.php
index 1ac543c5b281..4fdace91eddb 100644
--- a/app/Ninja/Repositories/CreditRepository.php
+++ b/app/Ninja/Repositories/CreditRepository.php
@@ -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');
diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php
index be6e625b1f73..7ab30fee05bf 100644
--- a/app/Ninja/Repositories/InvoiceRepository.php
+++ b/app/Ninja/Repositories/InvoiceRepository.php
@@ -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 {
diff --git a/app/Ninja/Transformers/AccountTransformer.php b/app/Ninja/Transformers/AccountTransformer.php
index 7e50baff9e6a..d812d243628f 100644
--- a/app/Ninja/Transformers/AccountTransformer.php
+++ b/app/Ninja/Transformers/AccountTransformer.php
@@ -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)
diff --git a/app/Ninja/Transformers/ClientTransformer.php b/app/Ninja/Transformers/ClientTransformer.php
index 2f4a8cdf44aa..8423786fd7d4 100644
--- a/app/Ninja/Transformers/ClientTransformer.php
+++ b/app/Ninja/Transformers/ClientTransformer.php
@@ -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,
diff --git a/app/Ninja/Transformers/ContactTransformer.php b/app/Ninja/Transformers/ContactTransformer.php
index 5c5cd7d4b00d..51114da5aee4 100644
--- a/app/Ninja/Transformers/ContactTransformer.php
+++ b/app/Ninja/Transformers/ContactTransformer.php
@@ -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
];
}
}
\ No newline at end of file
diff --git a/app/Ninja/Transformers/EntityTransformer.php b/app/Ninja/Transformers/EntityTransformer.php
index 11ba0d1fc356..f3d61f94de8d 100644
--- a/app/Ninja/Transformers/EntityTransformer.php
+++ b/app/Ninja/Transformers/EntityTransformer.php
@@ -1,14 +1,35 @@
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);
}
}
diff --git a/app/Ninja/Transformers/InvoiceTransformer.php b/app/Ninja/Transformers/InvoiceTransformer.php
index 0024e44117d4..8415374d4e00 100644
--- a/app/Ninja/Transformers/InvoiceTransformer.php
+++ b/app/Ninja/Transformers/InvoiceTransformer.php
@@ -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
];
}
}
\ No newline at end of file
diff --git a/app/Ninja/Transformers/PaymentTransformer.php b/app/Ninja/Transformers/PaymentTransformer.php
new file mode 100644
index 000000000000..6ec0b13da78e
--- /dev/null
+++ b/app/Ninja/Transformers/PaymentTransformer.php
@@ -0,0 +1,55 @@
+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,
+ ];
+ }
+}
\ No newline at end of file
diff --git a/app/Ninja/Transformers/QuoteTransformer.php b/app/Ninja/Transformers/QuoteTransformer.php
index 716b29656a59..d012aceb45b8 100644
--- a/app/Ninja/Transformers/QuoteTransformer.php
+++ b/app/Ninja/Transformers/QuoteTransformer.php
@@ -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)
diff --git a/app/Ninja/Transformers/TaskTransformer.php b/app/Ninja/Transformers/TaskTransformer.php
new file mode 100644
index 000000000000..908a8118aaea
--- /dev/null
+++ b/app/Ninja/Transformers/TaskTransformer.php
@@ -0,0 +1,50 @@
+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()
+ ];
+ }
+}
\ No newline at end of file
diff --git a/app/Ninja/Transformers/UserAccountTransformer.php b/app/Ninja/Transformers/UserAccountTransformer.php
index 18992ae1706f..bc49a96c546a 100644
--- a/app/Ninja/Transformers/UserAccountTransformer.php
+++ b/app/Ninja/Transformers/UserAccountTransformer.php
@@ -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)
diff --git a/app/Services/DatatableService.php b/app/Services/DatatableService.php
index 32d5909800f2..67636ebc96ad 100644
--- a/app/Services/DatatableService.php
+++ b/app/Services/DatatableService.php
@@ -12,7 +12,8 @@ class DatatableService
if ($actions && $showCheckbox) {
$table->addColumn('checkbox', function ($model) {
- return ' ';
+ return ' ';
});
}
@@ -81,14 +82,17 @@ class DatatableService
}
if ($entityType != ENTITY_USER || $model->public_id) {
- $str .= "
public_id})\">" . trans("texts.archive_{$entityType}") . " ";
+ $str .= "public_id})\">"
+ . trans("texts.archive_{$entityType}") . " ";
}
} else {
- $str .= "public_id})\">" . trans("texts.restore_{$entityType}") . " ";
+ $str .= "public_id})\">"
+ . trans("texts.restore_{$entityType}") . " ";
}
if (property_exists($model, 'is_deleted') && !$model->is_deleted) {
- $str .= "public_id})\">" . trans("texts.delete_{$entityType}") . " ";
+ $str .= "public_id})\">"
+ . trans("texts.delete_{$entityType}") . " ";
}
return $str.'';
diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php
index ebab4b8780b1..796c9815debe 100644
--- a/app/Services/ImportService.php
+++ b/app/Services/ImportService.php
@@ -1,10 +1,10 @@
- $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;
}
-
}
diff --git a/app/Services/PaymentService.php b/app/Services/PaymentService.php
index 19c95a23bfbf..eee8c814f268 100644
--- a/app/Services/PaymentService.php
+++ b/app/Services/PaymentService.php
@@ -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();
diff --git a/c3.php b/c3.php
index 96720d95adc9..cadb3a399b95 100755
--- a/c3.php
+++ b/c3.php
@@ -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
\ No newline at end of file
+// @codeCoverageIgnoreEnd
diff --git a/composer.json b/composer.json
index 85579d8c9b44..9f128c3f76a7 100644
--- a/composer.json
+++ b/composer.json
@@ -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"
},
diff --git a/composer.lock b/composer.lock
index e532d0739db5..7066d4070c87 100644
--- a/composer.lock
+++ b/composer.lock
@@ -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": [],
diff --git a/config/database.php b/config/database.php
index d6b202f23b88..082117ea767f 100644
--- a/config/database.php
+++ b/config/database.php
@@ -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,
+ ],
- ],
+ ],
];
diff --git a/public/favicon-v2.png b/public/favicon-v2.png
new file mode 100644
index 000000000000..9fdfcb9aae66
Binary files /dev/null and b/public/favicon-v2.png differ
diff --git a/public/js/built.js b/public/js/built.js
index 46de4c96d734..73deb11cdd9f 100644
--- a/public/js/built.js
+++ b/public/js/built.js
@@ -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) {
diff --git a/public/js/pdf.pdfmake.js b/public/js/pdf.pdfmake.js
index fd57a6bf6270..49c0b579cd5e 100644
--- a/public/js/pdf.pdfmake.js
+++ b/public/js/pdf.pdfmake.js
@@ -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();
}
diff --git a/readme.md b/readme.md
index cb3a30fa2953..3bb80b1a58a7 100644
--- a/readme.md
+++ b/readme.md
@@ -7,7 +7,13 @@
[](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/)
diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php
index 6fa11cd5d2a6..8cac5e56ecea 100644
--- a/resources/lang/da/texts.php
+++ b/resources/lang/da/texts.php
@@ -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',
+
);
diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php
index ff6a6da5ac22..eae5510b0bcc 100644
--- a/resources/lang/de/texts.php
+++ b/resources/lang/de/texts.php
@@ -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',
+
);
diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php
index 82941ea6298a..bee2302645dc 100644
--- a/resources/lang/en/texts.php
+++ b/resources/lang/en/texts.php
@@ -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 fill in the description and cost ',
'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. 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',
+
+
);
diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php
index 0fb7664d7d67..f5236749c113 100644
--- a/resources/lang/es/texts.php
+++ b/resources/lang/es/texts.php
@@ -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',
+
);
diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php
index 4a6214f10233..ea2922644209 100644
--- a/resources/lang/es_ES/texts.php
+++ b/resources/lang/es_ES/texts.php
@@ -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',
+
);
diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php
index 22890d9b6050..76b4ee253113 100644
--- a/resources/lang/fr/texts.php
+++ b/resources/lang/fr/texts.php
@@ -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',
);
diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php
index 13d3e367d999..4f94ef98f65d 100644
--- a/resources/lang/fr_CA/texts.php
+++ b/resources/lang/fr_CA/texts.php
@@ -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',
+
);
diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php
index a35a42cbb2ed..a73598fa3e98 100644
--- a/resources/lang/it/texts.php
+++ b/resources/lang/it/texts.php
@@ -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',
);
diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php
index 9aee3cd86e2a..efb4248a6a3e 100644
--- a/resources/lang/lt/texts.php
+++ b/resources/lang/lt/texts.php
@@ -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',
);
diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php
index 3c50871fa650..43002f7f5bcc 100644
--- a/resources/lang/nb_NO/texts.php
+++ b/resources/lang/nb_NO/texts.php
@@ -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',
);
diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php
index a071965d5eeb..e366bf5eca5c 100644
--- a/resources/lang/nl/texts.php
+++ b/resources/lang/nl/texts.php
@@ -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',
);
diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php
index d673bc6b9c08..70c01675d321 100644
--- a/resources/lang/pt_BR/texts.php
+++ b/resources/lang/pt_BR/texts.php
@@ -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',
);
diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php
index 7401020eb6d7..230eafb8ab26 100644
--- a/resources/lang/sv/texts.php
+++ b/resources/lang/sv/texts.php
@@ -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',
+
);
diff --git a/resources/views/accounts/account_gateway.blade.php b/resources/views/accounts/account_gateway.blade.php
index dfb47aaf9670..9c1f09cec351 100644
--- a/resources/views/accounts/account_gateway.blade.php
+++ b/resources/views/accounts/account_gateway.blade.php
@@ -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')) !!}
diff --git a/resources/views/accounts/import_export.blade.php b/resources/views/accounts/import_export.blade.php
index cab0b31b9d51..92f3c231508f 100644
--- a/resources/views/accounts/import_export.blade.php
+++ b/resources/views/accounts/import_export.blade.php
@@ -4,7 +4,6 @@
@parent
+@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 {
+
+
@@ -279,14 +200,14 @@ header h3 em {
{{ trans('texts.billing_method') }}
- {!! 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('') !!}
- {!! 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 {
- {!! 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 {
!!}
- {!! 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 {
- @if ($client && $account->showTokenCheckbox())
+ @if ($client && $account->showTokenCheckbox())
selectTokenCheckbox() ? 'CHECKED' : '' }} value="1" style="margin-left:0px; vertical-align:top">
{{ trans('texts.token_billing') }}
{!! trans('texts.token_billing_secure', ['stripe_link' => link_to('https://stripe.com/', 'Stripe.com', ['target' => '_blank'])]) !!}
- @endif
+ @endif
-
- @if (isset($acceptedCreditCardTypes))
+
+ @if (isset($acceptedCreditCardTypes))
@foreach ($acceptedCreditCardTypes as $card)
diff --git a/resources/views/payments/payment_css.blade.php b/resources/views/payments/payment_css.blade.php
new file mode 100644
index 000000000000..e22a15464561
--- /dev/null
+++ b/resources/views/payments/payment_css.blade.php
@@ -0,0 +1,130 @@
+
diff --git a/tests/_support/_generated/AcceptanceTesterActions.php b/tests/_support/_generated/AcceptanceTesterActions.php
index 94bb9b320601..3135d9aa0510 100644
--- a/tests/_support/_generated/AcceptanceTesterActions.php
+++ b/tests/_support/_generated/AcceptanceTesterActions.php
@@ -1,4 +1,4 @@
-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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will *not* be true for strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will *not* be true for strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will ignore strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will ignore strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
- * seeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
- * seeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
- * dontSeeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
- * dontSeeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
- *
First
- *
Second
- *
Third
- * ```
- *
- * ```php
- * 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
* 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
+ * 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
*
* ```
*
- * @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
*
* ```
*
- * @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:
diff --git a/tests/_support/_generated/FunctionalTesterActions.php b/tests/_support/_generated/FunctionalTesterActions.php
index a3980a806784..edf786bc5c7e 100644
--- a/tests/_support/_generated/FunctionalTesterActions.php
+++ b/tests/_support/_generated/FunctionalTesterActions.php
@@ -1,4 +1,4 @@
-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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will *not* be true for strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will *not* be true for strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will ignore strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
* 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:
- *
- * - `
I am Stronger than thou
`
- * - ``
- *
- * But will ignore strings like:
- *
- * - `
Home `
- * - `
Home`
- * - ``
- *
- * 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
- * seeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
- * seeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
- * dontSeeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
- * dontSeeInSource('
Green eggs & ham ');
- * ```
- *
- * @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
* 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
- * 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
- * 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
- *
First
- *
Second
- *
Third
- * ```
- *
- * ```php
- * 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
- *