registered; } public static function isConfirmed() { return Auth::check() && Auth::user()->confirmed; } public static function isDatabaseSetup() { try { if (Schema::hasTable('accounts')) { return true; } } catch (Exception $e) { return false; } } public static function isDownForMaintenance() { return file_exists(storage_path() . '/framework/down'); } public static function isCron() { return php_sapi_name() == 'cli'; } public static function isTravis() { return env('TRAVIS') == 'true'; } public static function isNinja() { return self::isNinjaProd() || self::isNinjaDev(); } public static function isSelfHost() { return ! static::isNinjaProd(); } public static function isNinjaProd() { if (self::isReseller()) { return true; } return env('NINJA_PROD') == 'true'; } public static function isNinjaDev() { return env('NINJA_DEV') == 'true'; } public static function requireHTTPS() { if (Request::root() === 'http://ninja.dev' || Request::root() === 'http://ninja.dev:8000') { return false; } return self::isNinjaProd() || (isset($_ENV['REQUIRE_HTTPS']) && $_ENV['REQUIRE_HTTPS'] == 'true'); } public static function isReseller() { return self::getResllerType() ? true : false; } public static function clientViewCSS() { $account = false; if (Auth::check()) { $account = Auth::user()->account; } elseif ($contactKey = session('contact_key')) { if ($contact = \App\Models\Contact::whereContactKey($contactKey)->first()) { $account = $contact->account; } } if ( !$account && ! self::isNinja()) { // For self-hosted accounts, pick the first account $account = \App\Models\Account::first(); } return $account ? $account->clientViewCSS() : ''; } public static function getAccountFontsUrl($protocol = '') { $account = false; if (Auth::check()) { $account = Auth::user()->account; } elseif ($contactKey = session('contact_key')) { if ($contact = \App\Models\Contact::whereContactKey($contactKey)->first()) { $account = $contact->account; } } if ( !$account && ! self::isNinja()) { // For self-hosted accounts, pick the first account $account = \App\Models\Account::first(); } return $account ? $account->getFontsUrl($protocol) : false; } public static function isWhiteLabel() { $account = false; if (self::isNinja()) { if (Auth::check()) { $account = Auth::user()->account; } elseif ($contactKey = session('contact_key')) { if ($contact = \App\Models\Contact::whereContactKey($contactKey)->first()) { $account = $contact->account; } } } else { $account = \App\Models\Account::first(); } return $account ? $account->hasFeature(FEATURE_WHITE_LABEL) : false; } public static function getResllerType() { return isset($_ENV['RESELLER_TYPE']) ? $_ENV['RESELLER_TYPE'] : false; } public static function getTermsLink() { return static::isNinja() ? NINJA_WEB_URL.'/terms' : NINJA_WEB_URL.'/self-hosting-the-invoice-ninja-platform'; } public static function isOAuthEnabled() { $providers = [ SOCIAL_GOOGLE, SOCIAL_FACEBOOK, SOCIAL_GITHUB, SOCIAL_LINKEDIN, ]; foreach ($providers as $provider) { $key = strtoupper($provider) . '_CLIENT_ID'; if (isset($_ENV[$key]) && $_ENV[$key]) { return true; } } return false; } public static function allowNewAccounts() { return self::isNinja() || Auth::check(); } public static function isPro() { return Auth::check() && Auth::user()->isPro(); } public static function hasFeature($feature) { return Auth::check() && Auth::user()->hasFeature($feature); } public static function isAdmin() { return Auth::check() && Auth::user()->is_admin; } public static function hasPermission($permission, $requireAll = false) { return Auth::check() && Auth::user()->hasPermission($permission, $requireAll); } public static function hasAllPermissions($permission) { return Auth::check() && Auth::user()->hasPermission($permission); } public static function isTrial() { return Auth::check() && Auth::user()->isTrial(); } public static function isPaidPro() { return static::isPro() && ! static::isTrial(); } public static function isEnglish() { return App::getLocale() == 'en'; } public static function getDebugInfo() { if ($info = session('DEBUG_INFO')) { return $info; } $mysqlVersion = DB::select( DB::raw("select version() as version") )[0]->version; $accountKey = Auth::check() ? Auth::user()->account->account_key : ''; $info = "App Version: v" . NINJA_VERSION . "\\n" . "White Label: " . (Utils::isWhiteLabel() ? 'Yes' : 'No') . " - {$accountKey}\\n" . "Server OS: " . php_uname('s') . ' ' . php_uname('r') . "\\n" . "PHP Version: " . phpversion() . "\\n" . "MySQL Version: " . $mysqlVersion; session(['DEBUG_INFO' => $info]); return $info; } public static function getLocaleRegion() { $parts = explode('_', App::getLocale()); return count($parts) ? $parts[0] : 'en'; } public static function getUserType() { if (self::isNinja()) { return USER_TYPE_CLOUD_HOST; } else { return USER_TYPE_SELF_HOST; } } public static function getNewsFeedResponse($userType = false) { if (! $userType) { $userType = self::getUserType(); } $response = new stdClass(); $response->message = isset($_ENV["{$userType}_MESSAGE"]) ? $_ENV["{$userType}_MESSAGE"] : ''; $response->id = isset($_ENV["{$userType}_ID"]) ? $_ENV["{$userType}_ID"] : ''; $response->version = NINJA_VERSION; return $response; } public static function getProLabel($feature) { if (Auth::check() && ! Auth::user()->isPro() && $feature == ACCOUNT_ADVANCED_SETTINGS) { return ' PRO'; } else { return ''; } } public static function getPlanPrice($plan) { $term = $plan['term']; $numUsers = $plan['num_users']; $plan = $plan['plan']; if ($plan == PLAN_FREE) { $price = 0; } elseif ($plan == PLAN_PRO) { $price = PLAN_PRICE_PRO_MONTHLY; } elseif ($plan == PLAN_ENTERPRISE) { if ($numUsers <= 2) { $price = PLAN_PRICE_ENTERPRISE_MONTHLY_2; } elseif ($numUsers <= 5) { $price = PLAN_PRICE_ENTERPRISE_MONTHLY_5; } elseif ($numUsers <= 10) { $price = PLAN_PRICE_ENTERPRISE_MONTHLY_10; } elseif ($numUsers <= 20) { $price = PLAN_PRICE_ENTERPRISE_MONTHLY_20; } else { static::fatalError('Invalid number of users: ' . $numUsers); } } if ($term == PLAN_TERM_YEARLY) { $price = $price * 10; } return $price; } public static function getMinNumUsers($max) { if ($max <= 2) { return 1; } elseif ($max <= 5) { return 3; } elseif ($max <= 10) { return 6; } else { return 11; } } public static function basePath() { return substr($_SERVER['SCRIPT_NAME'], 0, strrpos($_SERVER['SCRIPT_NAME'], '/') + 1); } public static function trans($input, $module = false) { $data = []; foreach ($input as $field) { if ($field == 'checkbox') { $data[] = $field; } elseif ($field) { if ($module) { $data[] = mtrans($module, $field); } else { $data[] = trans("texts.$field"); } } else { $data[] = ''; } } return $data; } public static function fatalError($message = false, $exception = false) { if (! $message) { $message = 'An error occurred, please try again later.'; } static::logError($message.' '.$exception); $data = [ 'showBreadcrumbs' => false, 'hideHeader' => true, ]; return View::make('error', $data)->with('error', $message); } public static function getErrorString($exception) { $class = get_class($exception); $code = method_exists($exception, 'getStatusCode') ? $exception->getStatusCode() : $exception->getCode(); return "***{$class}*** [{$code}] : {$exception->getFile()} [Line {$exception->getLine()}] => {$exception->getMessage()}"; } public static function logError($error, $context = 'PHP', $info = false) { if ($error instanceof Exception) { $error = self::getErrorString($error); } $count = Session::get('error_count', 0); Session::put('error_count', ++$count); if ($count > 200) { return 'logged'; } $data = static::prepareErrorData($context); if ($info) { Log::info($error."\n", $data); } else { Log::error($error."\n", $data); } } public static function prepareErrorData($context) { return [ 'context' => $context, 'user_id' => Auth::check() ? Auth::user()->id : 0, 'account_id' => Auth::check() ? Auth::user()->account_id : 0, 'user_name' => Auth::check() ? Auth::user()->getDisplayName() : '', 'method' => Request::method(), 'url' => Input::get('url', Request::url()), 'previous' => url()->previous(), 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '', 'ip' => Request::getClientIp(), 'count' => Session::get('error_count', 0), 'is_console' => App::runningInConsole() ? 'yes' : 'no', 'is_api' => session('token_id') ? 'yes' : 'no', 'db_server' => config('database.default'), ]; } public static function getErrors() { $data = []; $filename = storage_path('logs/laravel-error.log'); if (! file_exists($filename)) { return $data; } $errors = file($filename); for ($i=count($errors)-1; $i>=0; $i--) { $data[] = $errors[$i]; if (count($data) >= 10) { break; } } return $data; } public static function parseFloat($value) { $value = preg_replace('/[^0-9\.\-]/', '', $value); return floatval($value); } public static function parseInt($value) { $value = preg_replace('/[^0-9]/', '', $value); return intval($value); } public static function getFromCache($id, $type) { $cache = Cache::get($type); if (! $cache) { static::logError("Cache for {$type} is not set"); return null; } $data = $cache->filter(function ($item) use ($id) { return $item->id == $id; }); return $data->first(); } public static function formatMoney($value, $currencyId = false, $countryId = false, $decorator = false) { $value = floatval($value); if (! $currencyId) { $currencyId = Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY); } if (! $decorator) { $decorator = Session::get(SESSION_CURRENCY_DECORATOR, CURRENCY_DECORATOR_SYMBOL); } if (! $countryId && Auth::check()) { $countryId = Auth::user()->account->country_id; } $currency = self::getFromCache($currencyId, 'currencies'); $thousand = $currency->thousand_separator; $decimal = $currency->decimal_separator; $precision = $currency->precision; $code = $currency->code; $swapSymbol = $currency->swap_currency_symbol; if ($countryId && $currencyId == CURRENCY_EURO) { $country = self::getFromCache($countryId, 'countries'); $swapSymbol = $country->swap_currency_symbol; if ($country->thousand_separator) { $thousand = $country->thousand_separator; } if ($country->decimal_separator) { $decimal = $country->decimal_separator; } } $value = number_format($value, $precision, $decimal, $thousand); $symbol = $currency->symbol; if ($decorator == CURRENCY_DECORATOR_NONE) { return $value; } elseif ($decorator == CURRENCY_DECORATOR_CODE || ! $symbol) { return "{$value} {$code}"; } elseif ($swapSymbol) { return "{$value} " . trim($symbol); } else { return "{$symbol}{$value}"; } } public static function pluralize($string, $count) { $field = $count == 1 ? $string : $string.'s'; $string = trans("texts.$field", ['count' => $count]); return $string; } public static function pluralizeEntityType($type) { if (! self::isNinjaProd()) { if ($module = \Module::find($type)) { return $module->get('plural', $type); } } if ($type === ENTITY_EXPENSE_CATEGORY) { return 'expense_categories'; } else { return $type . 's'; } } public static function maskAccountNumber($value) { $length = strlen($value); if ($length < 4) { str_repeat('*', 16); } $lastDigits = substr($value, -4); return str_repeat('*', $length - 4) . $lastDigits; } // http://wephp.co/detect-credit-card-type-php/ public static function getCardType($number) { $number = preg_replace('/[^\d]/', '', $number); if (preg_match('/^3[47][0-9]{13}$/', $number)) { return 'American Express'; } elseif (preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', $number)) { return 'Diners Club'; } elseif (preg_match('/^6(?:011|5[0-9][0-9])[0-9]{12}$/', $number)) { return 'Discover'; } elseif (preg_match('/^(?:2131|1800|35\d{3})\d{11}$/', $number)) { return 'JCB'; } elseif (preg_match('/^5[1-5][0-9]{14}$/', $number)) { return 'MasterCard'; } elseif (preg_match('/^4[0-9]{12}(?:[0-9]{3})?$/', $number)) { return 'Visa'; } else { return 'Unknown'; } } public static function toArray($data) { return json_decode(json_encode((array) $data), true); } public static function toSpaceCase($string) { return preg_replace('/([a-z])([A-Z])/s', '$1 $2', $string); } public static function toSnakeCase($string) { return preg_replace('/([a-z])([A-Z])/s', '$1_$2', $string); } public static function toCamelCase($string) { return lcfirst(static::toClassCase($string)); } public static function toClassCase($string) { return str_replace(' ', '', ucwords(str_replace('_', ' ', $string))); } public static function timestampToDateTimeString($timestamp) { $timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); $format = Session::get(SESSION_DATETIME_FORMAT, DEFAULT_DATETIME_FORMAT); return self::timestampToString($timestamp, $timezone, $format); } public static function timestampToDateString($timestamp) { $timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); $format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT); return self::timestampToString($timestamp, $timezone, $format); } public static function dateToString($date) { if (! $date) { return false; } if ($date instanceof DateTime) { $dateTime = $date; } else { $dateTime = new DateTime($date); } $timestamp = $dateTime->getTimestamp(); $format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT); return self::timestampToString($timestamp, false, $format); } public static function timestampToString($timestamp, $timezone, $format) { if (! $timestamp) { return ''; } $date = Carbon::createFromTimeStamp($timestamp); if ($timezone) { $date->tz = $timezone; } if ($date->year < 1900) { return ''; } return $date->format($format); } public static function toSqlDate($date, $formatResult = true) { if (! $date) { return; } $format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT); $dateTime = DateTime::createFromFormat($format, $date); if (! $dateTime) { return $date; } else { return $formatResult ? $dateTime->format('Y-m-d') : $dateTime; } } public static function fromSqlDate($date, $formatResult = true) { if (! $date || $date == '0000-00-00') { return ''; } $format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT); $dateTime = DateTime::createFromFormat('Y-m-d', $date); if (! $dateTime) { return $date; } else { return $formatResult ? $dateTime->format($format) : $dateTime; } } public static function fromSqlDateTime($date, $formatResult = true) { if (! $date || $date == '0000-00-00 00:00:00') { return ''; } $timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); $format = Session::get(SESSION_DATETIME_FORMAT, DEFAULT_DATETIME_FORMAT); $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', $date); $dateTime->setTimeZone(new DateTimeZone($timezone)); return $formatResult ? $dateTime->format($format) : $dateTime; } public static function formatTime($t) { // http://stackoverflow.com/a/3172665 $f = ':'; return sprintf('%02d%s%02d%s%02d', floor($t / 3600), $f, ($t / 60) % 60, $f, $t % 60); } public static function today($formatResult = true) { $timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); $format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT); $date = date_create(null, new DateTimeZone($timezone)); if ($formatResult) { return $date->format($format); } else { return $date; } } public static function processVariables($str, $client = false) { if (! $str) { return ''; } $variables = ['MONTH', 'QUARTER', 'YEAR']; for ($i = 0; $i < count($variables); $i++) { $variable = $variables[$i]; $regExp = '/:'.$variable.'[+-]?[\d]*/'; preg_match_all($regExp, $str, $matches); $matches = $matches[0]; if (count($matches) == 0) { continue; } usort($matches, function ($a, $b) { return strlen($b) - strlen($a); }); foreach ($matches as $match) { $offset = 0; $addArray = explode('+', $match); $minArray = explode('-', $match); if (count($addArray) > 1) { $offset = intval($addArray[1]); } elseif (count($minArray) > 1) { $offset = intval($minArray[1]) * -1; } $locale = $client && $client->language_id ? $client->language->locale : null; $val = self::getDatePart($variable, $offset, $locale); $str = str_replace($match, $val, $str); } } return $str; } private static function getDatePart($part, $offset, $locale) { $offset = intval($offset); if ($part == 'MONTH') { return self::getMonth($offset, $locale); } elseif ($part == 'QUARTER') { return self::getQuarter($offset); } elseif ($part == 'YEAR') { return self::getYear($offset); } } public static function getMonthOptions() { $months = []; for ($i = 1; $i <= count(static::$months); $i++) { $month = static::$months[$i - 1]; $number = $i < 10 ? '0' . $i : $i; $months["2000-{$number}-01"] = trans("texts.{$month}"); } return $months; } private static function getMonth($offset, $locale) { $months = static::$months; $month = intval(date('n')) - 1; $month += $offset; $month = $month % 12; if ($month < 0) { $month += 12; } return trans('texts.' . $months[$month], [], null, $locale); } private static function getQuarter($offset) { $month = intval(date('n')) - 1; $quarter = floor(($month + 3) / 3); $quarter += $offset; $quarter = $quarter % 4; if ($quarter == 0) { $quarter = 4; } return 'Q'.$quarter; } private static function getYear($offset) { $year = intval(date('Y')); return $year + $offset; } public static function getEntityName($entityType) { return ucwords(self::toCamelCase($entityType)); } public static function getClientDisplayName($model) { if ($model->client_name) { return $model->client_name; } elseif ($model->first_name || $model->last_name) { return $model->first_name.' '.$model->last_name; } else { return $model->email ?: ''; } } public static function getVendorDisplayName($model) { if (is_null($model)) { return ''; } if ($model->vendor_name) { return $model->vendor_name; } return 'No vendor name'; } public static function getPersonDisplayName($firstName, $lastName, $email) { if ($firstName || $lastName) { return $firstName.' '.$lastName; } elseif ($email) { return $email; } else { return trans('texts.guest'); } } public static function generateLicense() { $parts = []; for ($i = 0; $i < 5; $i++) { $parts[] = strtoupper(str_random(4)); } return implode('-', $parts); } public static function lookupEventId($eventName) { if ($eventName == 'create_client') { return EVENT_CREATE_CLIENT; } elseif ($eventName == 'create_invoice') { return EVENT_CREATE_INVOICE; } elseif ($eventName == 'create_quote') { return EVENT_CREATE_QUOTE; } elseif ($eventName == 'create_payment') { return EVENT_CREATE_PAYMENT; } elseif ($eventName == 'create_vendor') { return EVENT_CREATE_VENDOR; } else { return false; } } public static function notifyZapier($subscription, $data) { $curl = curl_init(); $jsonEncodedData = json_encode($data); $opts = [ CURLOPT_URL => $subscription->target_url, CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POST => 1, CURLOPT_POSTFIELDS => $jsonEncodedData, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Content-Length: '.strlen($jsonEncodedData)], ]; curl_setopt_array($curl, $opts); $result = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); if ($status == 410) { $subscription->delete(); } } public static function getApiHeaders($count = 0) { return [ 'Content-Type' => 'application/json', //'Access-Control-Allow-Origin' => '*', //'Access-Control-Allow-Methods' => 'GET', //'Access-Control-Allow-Headers' => 'Origin, Content-Type, Accept, Authorization, X-Requested-With', //'Access-Control-Allow-Credentials' => 'true', 'X-Total-Count' => $count, 'X-Ninja-Version' => NINJA_VERSION, //'X-Rate-Limit-Limit' - The number of allowed requests in the current period //'X-Rate-Limit-Remaining' - The number of remaining requests in the current period //'X-Rate-Limit-Reset' - The number of seconds left in the current period, ]; } public static function isEmpty($value) { return ! $value || $value == '0' || $value == '0.00' || $value == '0,00'; } public static function startsWith($haystack, $needle) { return $needle === '' || strpos($haystack, $needle) === 0; } public static function endsWith($haystack, $needle) { return $needle === '' || substr($haystack, -strlen($needle)) === $needle; } public static function getEntityRowClass($model) { $str = ''; if (property_exists($model, 'is_deleted')) { $str = $model->is_deleted ? 'DISABLED ' : ''; if ($model->is_deleted) { $str .= 'ENTITY_DELETED '; } } if ($model->deleted_at && $model->deleted_at != '0000-00-00') { $str .= 'ENTITY_ARCHIVED '; } return $str; } public static function exportData($output, $data, $headers = false) { if ($headers) { fputcsv($output, $headers); } elseif (count($data) > 0) { fputcsv($output, array_keys($data[0])); } foreach ($data as $record) { fputcsv($output, $record); } fwrite($output, "\n"); } public static function getFirst($values) { if (is_array($values)) { return count($values) ? $values[0] : false; } else { return $values; } } // nouns in German and French should be uppercase // TODO remove this public static function transFlowText($key) { $str = trans("texts.$key"); if (! in_array(App::getLocale(), ['de', 'fr'])) { $str = strtolower($str); } return $str; } public static function getSubdomain($url) { $parts = parse_url($url); $subdomain = ''; if (isset($parts['host'])) { $host = explode('.', $parts['host']); if (count($host) > 2) { $subdomain = $host[0]; } } return $subdomain; } public static function getSubdomainPlaceholder() { return static::getSubdomain(SITE_URL); } public static function getDomainPlaceholder() { $parts = parse_url(SITE_URL); $domain = ''; if (isset($parts['host'])) { $host = explode('.', $parts['host']); if (count($host) > 2) { array_shift($host); $domain .= implode('.', $host); } else { $domain .= $parts['host']; } } if (isset($parts['path'])) { $domain .= $parts['path']; } return $domain; } public static function replaceSubdomain($domain, $subdomain) { $parsedUrl = parse_url($domain); $host = explode('.', $parsedUrl['host']); if (count($host) > 0) { $oldSubdomain = $host[0]; $domain = str_replace("://{$oldSubdomain}.", "://{$subdomain}.", $domain); } return $domain; } public static function splitName($name) { $name = trim($name); $lastName = (strpos($name, ' ') === false) ? '' : preg_replace('#.*\s([\w-]*)$#', '$1', $name); $firstName = trim(preg_replace('#'.$lastName.'#', '', $name)); return [$firstName, $lastName]; } public static function decodePDF($string) { $string = str_replace('data:application/pdf;base64,', '', $string); return base64_decode($string); } public static function cityStateZip($city, $state, $postalCode, $swap) { $str = $city; if ($state) { if ($str) { $str .= ', '; } $str .= $state; } if ($swap) { return $postalCode . ' ' . $str; } else { return $str . ' ' . $postalCode; } } public static function formatWebsite($link) { if (! $link) { return ''; } $title = $link; if (substr($link, 0, 4) != 'http') { $link = 'http://' . $link; } return link_to($link, $title, ['target' => '_blank']); } public static function wrapAdjustment($adjustment, $currencyId, $countryId) { $class = $adjustment <= 0 ? 'success' : 'default'; $adjustment = self::formatMoney($adjustment, $currencyId, $countryId); return "

$adjustment

"; } public static function copyContext($entity1, $entity2) { if (! $entity2) { return $entity1; } $fields = [ 'contact_id', 'payment_id', 'invoice_id', 'credit_id', 'invitation_id', ]; $fields1 = $entity1->getAttributes(); $fields2 = $entity2->getAttributes(); foreach ($fields as $field) { if (isset($fields2[$field]) && $fields2[$field]) { $entity1->$field = $entity2->$field; } } return $entity1; } public static function addHttp($url) { if (! preg_match('~^(?:f|ht)tps?://~i', $url)) { $url = 'http://' . $url; } return $url; } public static function setupWePay($accountGateway = null) { if (WePay::getEnvironment() == 'none') { if (WEPAY_ENVIRONMENT == WEPAY_STAGE) { WePay::useStaging(WEPAY_CLIENT_ID, WEPAY_CLIENT_SECRET); } else { WePay::useProduction(WEPAY_CLIENT_ID, WEPAY_CLIENT_SECRET); } } if ($accountGateway) { return new WePay($accountGateway->getConfig()->accessToken); } else { return new WePay(null); } } /** * Gets an array of weekday names (in English). * * @see getTranslatedWeekdayNames() * * @return \Illuminate\Support\Collection */ public static function getWeekdayNames() { return collect(static::$weekdayNames); } /** * Gets an array of translated weekday names. * * @return \Illuminate\Support\Collection */ public static function getTranslatedWeekdayNames() { return collect(static::$weekdayNames)->transform(function ($day) { return trans('texts.'.strtolower($day)); }); } public static function getReadableUrl($path) { $url = static::getDocsUrl($path); $parts = explode('/', $url); $part = $parts[count($parts) - 1]; $part = str_replace('#', '> ', $part); $part = str_replace(['.html', '-', '_'], ' ', $part); if ($part) { return trans('texts.user_guide') . ': ' . ucwords($part); } else { return trans('texts.user_guide'); } } public static function getDocsUrl($path) { $page = ''; $parts = explode('/', $path); $first = count($parts) ? $parts[0] : false; $second = count($parts) > 1 ? $parts[1] : false; $entityTypes = [ 'clients', 'invoices', 'payments', 'recurring_invoices', 'credits', 'quotes', 'tasks', 'expenses', 'vendors', ]; if ($path == 'dashboard') { $page = '/introduction.html#dashboard'; } elseif (in_array($path, $entityTypes)) { $page = "/{$path}.html#list-" . str_replace('_', '-', $path); } elseif (in_array($first, $entityTypes)) { $action = ($first == 'payments' || $first == 'credits') ? 'enter' : 'create'; $page = "/{$first}.html#{$action}-" . substr(str_replace('_', '-', $first), 0, -1); } elseif ($first == 'expense_categories') { $page = '/expenses.html#expense-categories'; } elseif ($first == 'settings') { if ($second == 'bank_accounts') { $page = ''; // TODO write docs } elseif (in_array($second, \App\Models\Account::$basicSettings)) { if ($second == 'products') { $second = 'product_library'; } elseif ($second == 'notifications') { $second = 'email_notifications'; } $page = '/settings.html#' . str_replace('_', '-', $second); } elseif (in_array($second, \App\Models\Account::$advancedSettings)) { $page = "/{$second}.html"; } elseif ($second == 'customize_design') { $page = '/invoice_design.html#customize'; } } elseif ($first == 'tax_rates') { $page = '/settings.html#tax-rates'; } elseif ($first == 'products') { $page = '/settings.html#product-library'; } elseif ($first == 'users') { $page = '/user_management.html#create-user'; } return url(NINJA_DOCS_URL . $page); } public static function calculateTaxes($amount, $taxRate1, $taxRate2) { $tax1 = round($amount * $taxRate1 / 100, 2); $tax2 = round($amount * $taxRate2 / 100, 2); return round($amount + $tax1 + $tax2, 2); } public static function roundSignificant($value, $precision = 2) { if (round($value, 3) != $value) { $precision = 4; } elseif (round($value, 2) != $value) { $precision = 3; } elseif (round($value, 1) != $value) { $precision = 2; } return number_format($value, $precision, '.', ''); } public static function truncateString($string, $length) { return strlen($string) > $length ? rtrim(substr($string, 0, $length)) . '...' : $string; } // http://stackoverflow.com/a/14238078/497368 public static function isInterlaced($filename) { $handle = fopen($filename, 'r'); $contents = fread($handle, 32); fclose($handle); return( ord($contents[28]) != 0 ); } //Source: https://stackoverflow.com/questions/3302857/algorithm-to-get-the-excel-like-column-name-of-a-number public static function num2alpha($n) { for($r = ""; $n >= 0; $n = intval($n / 26) - 1) $r = chr($n%26 + 0x41) . $r; return $r; } /** * Replace language-specific characters by ASCII-equivalents. * @param string $s * @return string * Source: https://stackoverflow.com/questions/3371697/replacing-accented-characters-php/16427125#16427125 */ public static function normalizeChars($s) { $replace = array( 'ъ'=>'-', 'Ь'=>'-', 'Ъ'=>'-', 'ь'=>'-', 'Ă'=>'A', 'Ą'=>'A', 'À'=>'A', 'Ã'=>'A', 'Á'=>'A', 'Æ'=>'A', 'Â'=>'A', 'Å'=>'A', 'Ä'=>'Ae', 'Þ'=>'B', 'Ć'=>'C', 'ץ'=>'C', 'Ç'=>'C', 'È'=>'E', 'Ę'=>'E', 'É'=>'E', 'Ë'=>'E', 'Ê'=>'E', 'Ğ'=>'G', 'İ'=>'I', 'Ï'=>'I', 'Î'=>'I', 'Í'=>'I', 'Ì'=>'I', 'Ł'=>'L', 'Ñ'=>'N', 'Ń'=>'N', 'Ø'=>'O', 'Ó'=>'O', 'Ò'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'Oe', 'Ş'=>'S', 'Ś'=>'S', 'Ș'=>'S', 'Š'=>'S', 'Ț'=>'T', 'Ù'=>'U', 'Û'=>'U', 'Ú'=>'U', 'Ü'=>'Ue', 'Ý'=>'Y', 'Ź'=>'Z', 'Ž'=>'Z', 'Ż'=>'Z', 'â'=>'a', 'ǎ'=>'a', 'ą'=>'a', 'á'=>'a', 'ă'=>'a', 'ã'=>'a', 'Ǎ'=>'a', 'а'=>'a', 'А'=>'a', 'å'=>'a', 'à'=>'a', 'א'=>'a', 'Ǻ'=>'a', 'Ā'=>'a', 'ǻ'=>'a', 'ā'=>'a', 'ä'=>'ae', 'æ'=>'ae', 'Ǽ'=>'ae', 'ǽ'=>'ae', 'б'=>'b', 'ב'=>'b', 'Б'=>'b', 'þ'=>'b', 'ĉ'=>'c', 'Ĉ'=>'c', 'Ċ'=>'c', 'ć'=>'c', 'ç'=>'c', 'ц'=>'c', 'צ'=>'c', 'ċ'=>'c', 'Ц'=>'c', 'Č'=>'c', 'č'=>'c', 'Ч'=>'ch', 'ч'=>'ch', 'ד'=>'d', 'ď'=>'d', 'Đ'=>'d', 'Ď'=>'d', 'đ'=>'d', 'д'=>'d', 'Д'=>'D', 'ð'=>'d', 'є'=>'e', 'ע'=>'e', 'е'=>'e', 'Е'=>'e', 'Ə'=>'e', 'ę'=>'e', 'ĕ'=>'e', 'ē'=>'e', 'Ē'=>'e', 'Ė'=>'e', 'ė'=>'e', 'ě'=>'e', 'Ě'=>'e', 'Є'=>'e', 'Ĕ'=>'e', 'ê'=>'e', 'ə'=>'e', 'è'=>'e', 'ë'=>'e', 'é'=>'e', 'ф'=>'f', 'ƒ'=>'f', 'Ф'=>'f', 'ġ'=>'g', 'Ģ'=>'g', 'Ġ'=>'g', 'Ĝ'=>'g', 'Г'=>'g', 'г'=>'g', 'ĝ'=>'g', 'ğ'=>'g', 'ג'=>'g', 'Ґ'=>'g', 'ґ'=>'g', 'ģ'=>'g', 'ח'=>'h', 'ħ'=>'h', 'Х'=>'h', 'Ħ'=>'h', 'Ĥ'=>'h', 'ĥ'=>'h', 'х'=>'h', 'ה'=>'h', 'î'=>'i', 'ï'=>'i', 'í'=>'i', 'ì'=>'i', 'į'=>'i', 'ĭ'=>'i', 'ı'=>'i', 'Ĭ'=>'i', 'И'=>'i', 'ĩ'=>'i', 'ǐ'=>'i', 'Ĩ'=>'i', 'Ǐ'=>'i', 'и'=>'i', 'Į'=>'i', 'י'=>'i', 'Ї'=>'i', 'Ī'=>'i', 'І'=>'i', 'ї'=>'i', 'і'=>'i', 'ī'=>'i', 'ij'=>'ij', 'IJ'=>'ij', 'й'=>'j', 'Й'=>'j', 'Ĵ'=>'j', 'ĵ'=>'j', 'я'=>'ja', 'Я'=>'ja', 'Э'=>'je', 'э'=>'je', 'ё'=>'jo', 'Ё'=>'jo', 'ю'=>'ju', 'Ю'=>'ju', 'ĸ'=>'k', 'כ'=>'k', 'Ķ'=>'k', 'К'=>'k', 'к'=>'k', 'ķ'=>'k', 'ך'=>'k', 'Ŀ'=>'l', 'ŀ'=>'l', 'Л'=>'l', 'ł'=>'l', 'ļ'=>'l', 'ĺ'=>'l', 'Ĺ'=>'l', 'Ļ'=>'l', 'л'=>'l', 'Ľ'=>'l', 'ľ'=>'l', 'ל'=>'l', 'מ'=>'m', 'М'=>'m', 'ם'=>'m', 'м'=>'m', 'ñ'=>'n', 'н'=>'n', 'Ņ'=>'n', 'ן'=>'n', 'ŋ'=>'n', 'נ'=>'n', 'Н'=>'n', 'ń'=>'n', 'Ŋ'=>'n', 'ņ'=>'n', 'ʼn'=>'n', 'Ň'=>'n', 'ň'=>'n', 'о'=>'o', 'О'=>'o', 'ő'=>'o', 'õ'=>'o', 'ô'=>'o', 'Ő'=>'o', 'ŏ'=>'o', 'Ŏ'=>'o', 'Ō'=>'o', 'ō'=>'o', 'ø'=>'o', 'ǿ'=>'o', 'ǒ'=>'o', 'ò'=>'o', 'Ǿ'=>'o', 'Ǒ'=>'o', 'ơ'=>'o', 'ó'=>'o', 'Ơ'=>'o', 'œ'=>'oe', 'Œ'=>'oe', 'ö'=>'oe', 'פ'=>'p', 'ף'=>'p', 'п'=>'p', 'П'=>'p', 'ק'=>'q', 'ŕ'=>'r', 'ř'=>'r', 'Ř'=>'r', 'ŗ'=>'r', 'Ŗ'=>'r', 'ר'=>'r', 'Ŕ'=>'r', 'Р'=>'r', 'р'=>'r', 'ș'=>'s', 'с'=>'s', 'Ŝ'=>'s', 'š'=>'s', 'ś'=>'s', 'ס'=>'s', 'ş'=>'s', 'С'=>'s', 'ŝ'=>'s', 'Щ'=>'sch', 'щ'=>'sch', 'ш'=>'sh', 'Ш'=>'sh', 'ß'=>'ss', 'т'=>'t', 'ט'=>'t', 'ŧ'=>'t', 'ת'=>'t', 'ť'=>'t', 'ţ'=>'t', 'Ţ'=>'t', 'Т'=>'t', 'ț'=>'t', 'Ŧ'=>'t', 'Ť'=>'t', '™'=>'tm', 'ū'=>'u', 'у'=>'u', 'Ũ'=>'u', 'ũ'=>'u', 'Ư'=>'u', 'ư'=>'u', 'Ū'=>'u', 'Ǔ'=>'u', 'ų'=>'u', 'Ų'=>'u', 'ŭ'=>'u', 'Ŭ'=>'u', 'Ů'=>'u', 'ů'=>'u', 'ű'=>'u', 'Ű'=>'u', 'Ǖ'=>'u', 'ǔ'=>'u', 'Ǜ'=>'u', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'У'=>'u', 'ǚ'=>'u', 'ǜ'=>'u', 'Ǚ'=>'u', 'Ǘ'=>'u', 'ǖ'=>'u', 'ǘ'=>'u', 'ü'=>'ue', 'в'=>'v', 'ו'=>'v', 'В'=>'v', 'ש'=>'w', 'ŵ'=>'w', 'Ŵ'=>'w', 'ы'=>'y', 'ŷ'=>'y', 'ý'=>'y', 'ÿ'=>'y', 'Ÿ'=>'y', 'Ŷ'=>'y', 'Ы'=>'y', 'ž'=>'z', 'З'=>'z', 'з'=>'z', 'ź'=>'z', 'ז'=>'z', 'ż'=>'z', 'ſ'=>'z', 'Ж'=>'zh', 'ж'=>'zh' ); return strtr($s, $replace); } }