diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php
index 8b459675b868..011a28aafc71 100644
--- a/app/Http/Controllers/AccountController.php
+++ b/app/Http/Controllers/AccountController.php
@@ -402,6 +402,8 @@ class AccountController extends BaseController
return AccountController::export();
} elseif ($section === ACCOUNT_INVOICE_SETTINGS) {
return AccountController::saveInvoiceSettings();
+ } elseif ($section === ACCOUNT_EMAIL_SETTINGS) {
+ return AccountController::saveEmailSettings();
} elseif ($section === ACCOUNT_INVOICE_DESIGN) {
return AccountController::saveInvoiceDesign();
} elseif ($section === ACCOUNT_CUSTOMIZE_DESIGN) {
@@ -432,11 +434,6 @@ class AccountController extends BaseController
{
if (Auth::user()->account->isPro()) {
$account = Auth::user()->account;
- $account->email_design_id = Input::get('email_design_id');
-
- if (Utils::isNinja()) {
- $account->enable_email_markup = Input::get('enable_email_markup') ? true : false;
- }
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
$subjectField = "email_subject_{$type}";
@@ -492,15 +489,10 @@ class AccountController extends BaseController
return Redirect::to('settings/' . ACCOUNT_PRODUCTS);
}
- private function saveInvoiceSettings()
+ private function saveEmailSettings()
{
if (Auth::user()->account->isPro()) {
-
- $rules = [
- 'invoice_number_pattern' => 'has_counter',
- 'quote_number_pattern' => 'has_counter',
- ];
-
+ $rules = [];
$user = Auth::user();
$iframeURL = preg_replace('/[^a-zA-Z0-9_\-\:\/\.]/', '', substr(strtolower(Input::get('iframe_url')), 0, MAX_IFRAME_URL_LENGTH));
$iframeURL = rtrim($iframeURL, "/");
@@ -516,13 +508,45 @@ class AccountController extends BaseController
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
- return Redirect::to('settings/' . ACCOUNT_INVOICE_SETTINGS)
+ return Redirect::to('settings/' . ACCOUNT_EMAIL_SETTINGS)
->withErrors($validator)
->withInput();
} else {
$account = Auth::user()->account;
$account->subdomain = $subdomain;
$account->iframe_url = $iframeURL;
+ $account->pdf_email_attachment = Input::get('pdf_email_attachment') ? true : false;
+ $account->email_design_id = Input::get('email_design_id');
+
+ if (Utils::isNinja()) {
+ $account->enable_email_markup = Input::get('enable_email_markup') ? true : false;
+ }
+
+ $account->save();
+ Session::flash('message', trans('texts.updated_settings'));
+ }
+ }
+
+ return Redirect::to('settings/' . ACCOUNT_EMAIL_SETTINGS);
+ }
+
+ private function saveInvoiceSettings()
+ {
+ if (Auth::user()->account->isPro()) {
+
+ $rules = [
+ 'invoice_number_pattern' => 'has_counter',
+ 'quote_number_pattern' => 'has_counter',
+ ];
+
+ $validator = Validator::make(Input::all(), $rules);
+
+ if ($validator->fails()) {
+ return Redirect::to('settings/' . ACCOUNT_INVOICE_SETTINGS)
+ ->withErrors($validator)
+ ->withInput();
+ } else {
+ $account = Auth::user()->account;
$account->custom_label1 = trim(Input::get('custom_label1'));
$account->custom_value1 = trim(Input::get('custom_value1'));
$account->custom_label2 = trim(Input::get('custom_label2'));
@@ -539,7 +563,6 @@ class AccountController extends BaseController
$account->invoice_number_counter = Input::get('invoice_number_counter');
$account->quote_number_prefix = Input::get('quote_number_prefix');
$account->share_counter = Input::get('share_counter') ? true : false;
- $account->pdf_email_attachment = Input::get('pdf_email_attachment') ? true : false;
$account->invoice_terms = Input::get('invoice_terms');
$account->invoice_footer = Input::get('invoice_footer');
$account->quote_terms = Input::get('quote_terms');
diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php
index 9f28cfad6181..eb400a5e3d9b 100644
--- a/app/Http/Controllers/ImportController.php
+++ b/app/Http/Controllers/ImportController.php
@@ -27,6 +27,9 @@ class ImportController extends BaseController
foreach (ImportService::$entityTypes as $entityType) {
if (Input::file("{$entityType}_file")) {
$files[$entityType] = Input::file("{$entityType}_file")->getRealPath();
+ if ($source === IMPORT_CSV) {
+ Session::forget("{$entityType}-data");
+ }
}
}
@@ -36,22 +39,13 @@ class ImportController extends BaseController
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'));
- }
+ return $this->showResult($skipped);
}
} catch (Exception $exception) {
Utils::logError($exception);
Session::flash('error', $exception->getMessage());
+ return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
}
-
- return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
}
public function doImportCSV()
@@ -62,19 +56,24 @@ class ImportController extends BaseController
try {
$skipped = $this->importService->importCSV($map, $headers);
-
- 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'));
- }
+ return $this->showResult($skipped);
} catch (Exception $exception) {
Utils::logError($exception);
Session::flash('error', $exception->getMessage());
+ return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
+ }
+ }
+
+ private function showResult($skipped)
+ {
+ 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'));
}
return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
diff --git a/app/Http/routes.php b/app/Http/routes.php
index f7533941f4c2..71989afbd866 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -26,13 +26,6 @@ Route::post('/setup', 'AppController@doSetup');
Route::get('/install', 'AppController@install');
Route::get('/update', 'AppController@update');
-/*
-// Codeception code coverage
-Route::get('/c3.php', function () {
- include '../c3.php';
-});
-*/
-
// Public pages
Route::get('/', 'HomeController@showIndex');
Route::get('/terms', 'HomeController@showTerms');
@@ -285,6 +278,7 @@ if (!defined('CONTACT_EMAIL')) {
define('ACCOUNT_ADVANCED_SETTINGS', 'advanced_settings');
define('ACCOUNT_INVOICE_SETTINGS', 'invoice_settings');
define('ACCOUNT_INVOICE_DESIGN', 'invoice_design');
+ define('ACCOUNT_EMAIL_SETTINGS', 'email_settings');
define('ACCOUNT_CHARTS_AND_REPORTS', 'charts_and_reports');
define('ACCOUNT_USER_MANAGEMENT', 'user_management');
define('ACCOUNT_DATA_VISUALIZATIONS', 'data_visualizations');
diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php
index 3f4e54657809..231c29abad93 100644
--- a/app/Libraries/Utils.php
+++ b/app/Libraries/Utils.php
@@ -896,5 +896,4 @@ class Utils
return $url;
}
-
}
diff --git a/app/Models/Account.php b/app/Models/Account.php
index fcd58ea5e436..3150f96a39fd 100644
--- a/app/Models/Account.php
+++ b/app/Models/Account.php
@@ -35,6 +35,7 @@ class Account extends Eloquent
public static $advancedSettings = [
ACCOUNT_INVOICE_SETTINGS,
ACCOUNT_INVOICE_DESIGN,
+ ACCOUNT_EMAIL_SETTINGS,
ACCOUNT_TEMPLATES_AND_REMINDERS,
ACCOUNT_CHARTS_AND_REPORTS,
ACCOUNT_DATA_VISUALIZATIONS,
diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php
index 1bf19bbfdbc3..7b6d46688aec 100644
--- a/app/Services/ImportService.php
+++ b/app/Services/ImportService.php
@@ -56,22 +56,26 @@ class ImportService
public function import($source, $files)
{
+ $skipped = [];
$imported_files = null;
foreach ($files as $entityType => $file) {
- $this->execute($source, $entityType, $file);
+ $result = $this->execute($source, $entityType, $file);
+ $skipped = array_merge($skipped, $result);
}
+
+ return $skipped;
}
private function execute($source, $entityType, $file)
{
$skipped = [];
- Excel::load($file, function ($reader) use ($source, $entityType, $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, $maps) {
+ $reader->each(function ($row) use ($source, $entityType, $maps, &$skipped) {
$result = $this->saveData($source, $entityType, $row, $maps);
if ( ! $result) {
diff --git a/c3.php b/c3.php
deleted file mode 100755
index cadb3a399b95..000000000000
--- a/c3.php
+++ /dev/null
@@ -1,258 +0,0 @@
- $value) {
- $_SERVER["HTTP_X_CODECEPTION_".strtoupper($key)] = $value;
- }
- }
-}
-
-if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) {
- return;
-}
-
-if (!function_exists('__c3_error')) {
- function __c3_error($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);
- }
- setcookie('CODECEPTION_CODECOVERAGE_ERROR', $message);
- }
-}
-
-// Autoload Codeception classes
-if (!class_exists('\\Codeception\\Codecept')) {
- 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 {
- __c3_error('Codeception is not loaded. Please check that either PHAR or Composer or PEAR package can be used');
- }
-}
-
-// 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)) {
- // 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 {
- \Codeception\Configuration::config($config_file);
-} catch (\Exception $e) {
- __c3_error($e->getMessage());
-}
-
-if (!defined('C3_CODECOVERAGE_MEDIATE_STORAGE')) {
-
- // workaround for 'zend_mm_heap corrupted' problem
- gc_disable();
-
- if ((integer)ini_get('memory_limit') < 384) {
- ini_set('memory_limit', '384M');
- }
-
- define('C3_CODECOVERAGE_MEDIATE_STORAGE', Codeception\Configuration::logDir() . 'c3tmp');
- define('C3_CODECOVERAGE_PROJECT_ROOT', Codeception\Configuration::projectDir());
- define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']);
-
- function __c3_build_html_report(PHP_CodeCoverage $codeCoverage, $path)
- {
- $writer = new PHP_CodeCoverage_Report_HTML();
- $writer->process($codeCoverage, $path . 'html');
-
- if (file_exists($path . '.tar')) {
- unlink($path . '.tar');
- }
-
- $phar = new PharData($path . '.tar');
- $phar->setSignatureAlgorithm(Phar::SHA1);
- $files = $phar->buildFromDirectory($path . 'html');
- array_map('unlink', $files);
-
- if (in_array('GZ', Phar::getSupportedCompression())) {
- if (file_exists($path . '.tar.gz')) {
- unlink($path . '.tar.gz');
- }
-
- $phar->compress(\Phar::GZ);
-
- // close the file so that we can rename it
- unset($phar);
-
- unlink($path . '.tar');
- rename($path . '.tar.gz', $path . '.tar');
- }
-
- return $path . '.tar';
- }
-
- function __c3_build_clover_report(PHP_CodeCoverage $codeCoverage, $path)
- {
- $writer = new PHP_CodeCoverage_Report_Clover();
- $writer->process($codeCoverage, $path . '.clover.xml');
-
- return $path . '.clover.xml';
- }
-
- function __c3_send_file($filename)
- {
- if (!headers_sent()) {
- readfile($filename);
- }
-
- return __c3_exit();
- }
-
- /**
- * @param $filename
- * @return null|PHP_CodeCoverage
- */
- function __c3_factory($filename)
- {
- $phpCoverage = is_readable($filename)
- ? unserialize(file_get_contents($filename))
- : new PHP_CodeCoverage();
-
-
- if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) {
- $suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'];
- try {
- $settings = \Codeception\Configuration::suiteSettings($suite, \Codeception\Configuration::config());
- } catch (Exception $e) {
- __c3_error($e->getMessage());
- }
- } else {
- $settings = \Codeception\Configuration::config();
- }
-
- try {
- \Codeception\Coverage\Filter::setup($phpCoverage)
- ->whiteList($settings)
- ->blackList($settings);
- } catch (Exception $e) {
- __c3_error($e->getMessage());
- }
-
- return $phpCoverage;
- }
-
- function __c3_exit()
- {
- if (!isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'])) {
- exit;
- }
- return null;
- }
-
- function __c3_clear()
- {
- \Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE);
- }
-}
-
-if (!is_dir(C3_CODECOVERAGE_MEDIATE_STORAGE)) {
- if (mkdir(C3_CODECOVERAGE_MEDIATE_STORAGE, 0777, true) === false) {
- __c3_error('Failed to create directory "' . C3_CODECOVERAGE_MEDIATE_STORAGE . '"');
- }
-}
-
-// evaluate base path for c3-related files
-$path = realpath(C3_CODECOVERAGE_MEDIATE_STORAGE) . DIRECTORY_SEPARATOR . 'codecoverage';
-
-$requested_c3_report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false);
-
-$complete_report = $current_report = $path . '.serialized';
-if ($requested_c3_report) {
- set_time_limit(0);
-
- $route = ltrim(strrchr($_SERVER['REQUEST_URI'], '/'), '/');
-
- if ($route == 'clear') {
- __c3_clear();
- return __c3_exit();
- }
-
- $codeCoverage = __c3_factory($complete_report);
-
- switch ($route) {
- case 'html':
- try {
- __c3_send_file(__c3_build_html_report($codeCoverage, $path));
- } catch (Exception $e) {
- __c3_error($e->getMessage());
- }
- return __c3_exit();
- case 'clover':
- try {
- __c3_send_file(__c3_build_clover_report($codeCoverage, $path));
- } catch (Exception $e) {
- __c3_error($e->getMessage());
- }
- return __c3_exit();
- case 'serialized':
- try {
- __c3_send_file($complete_report);
- } catch (Exception $e) {
- __c3_error($e->getMessage());
- }
- return __c3_exit();
- }
-
-} else {
- $codeCoverage = __c3_factory($current_report);
- $codeCoverage->start(C3_CODECOVERAGE_TESTNAME);
- if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) {
- register_shutdown_function(
- function () use ($codeCoverage, $current_report) {
- $codeCoverage->stop();
- file_put_contents($current_report, serialize($codeCoverage));
- }
- );
- }
-}
-
-// @codeCoverageIgnoreEnd
diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php
index 7ddad61bc6af..e581000b9f30 100644
--- a/resources/lang/en/texts.php
+++ b/resources/lang/en/texts.php
@@ -976,5 +976,5 @@ return array(
'color_help' => 'Note: the primary color is also used in the client portal and custom email designs.',
'token_expired' => 'Validation token was expired. Please try again.',
-
+ 'invoice_link' => 'Invoice Link',
);
diff --git a/resources/views/accounts/email_settings.blade.php b/resources/views/accounts/email_settings.blade.php
new file mode 100644
index 000000000000..2bc11b45bb15
--- /dev/null
+++ b/resources/views/accounts/email_settings.blade.php
@@ -0,0 +1,135 @@
+@extends('header')
+
+@section('content')
+ @parent
+ @include('accounts.nav', ['selected' => ACCOUNT_EMAIL_SETTINGS, 'advanced' => true])
+
+ {!! Former::open()->addClass('warn-on-exit') !!}
+ {{ Former::populate($account) }}
+ {{ Former::populateField('pdf_email_attachment', intval($account->pdf_email_attachment)) }}
+ {{ Former::populateField('enable_email_markup', intval($account->enable_email_markup)) }}
+
+