Files
snipe-it/app/Helpers/Helper.php
T
snipe d6769443a9 Squashed commit of the following:
commit 399c7590cd
Merge: d0c5ba70f eb67d1b06
Author: snipe <snipe@snipe.net>
Date:   Thu Dec 15 14:19:41 2022 -0800

    Merge pull request #12209 from snipe/fixes/error_downloading_unaccepted_assets

    Fixed 500 when downloading the Unaccepted Assets report  [sc-19555]

commit d0c5ba70f6
Merge: 29c2ff56e d9a21cce0
Author: snipe <snipe@snipe.net>
Date:   Thu Dec 15 12:42:29 2022 -0800

    Merge pull request #12242 from inietov/features/add_purchase_cost_column

    Added `purchase_cost` to user's default view [sc-19680]

commit d9a21cce00
Author: Ivan Nieto Vivanco <inietov@gmail.com>
Date:   Thu Dec 15 14:12:05 2022 -0600

    Add other items' purchase_cost columns to the same permission

commit 29c2ff56ec
Merge: 3e7975b2c 1fe0bfe17
Author: snipe <snipe@snipe.net>
Date:   Thu Dec 15 11:26:49 2022 -0800

    Merge pull request #12188 from snipe/fixes/decrease_logging_for_saml_when_not_enabled

    Removed extra logging case that was very noisy

commit 3e7975b2c3
Merge: 227fef76e d870bc3b0
Author: snipe <snipe@snipe.net>
Date:   Thu Dec 15 11:25:53 2022 -0800

    Merge pull request #12250 from akemidx/grey_out_pw_reset_button

    Fixed: Grey out pw reset button for consistency

commit d870bc3b02
Author: akemidx <kojotek.dx@gmail.com>
Date:   Thu Dec 15 14:19:51 2022 -0500

    nested if loop

commit 227fef76ee
Merge: 418ddcfac 9d44720ff
Author: snipe <snipe@snipe.net>
Date:   Thu Dec 15 11:06:53 2022 -0800

    Merge pull request #11736 from Godmartinz/gh6508_ldap_default_group

    Adds a permission group selection for directory sync

commit 9d44720ffd
Author: Godfrey M <godmartinz@gmail.com>
Date:   Thu Dec 15 11:02:34 2022 -0800

    reverted changes to composer.lock

commit 9f3f0a25ed
Author: Godfrey M <godmartinz@gmail.com>
Date:   Thu Dec 15 10:53:45 2022 -0800

    reverted changes to composer.lock

commit 2e228ccb0b
Author: Godfrey M <godmartinz@gmail.com>
Date:   Thu Dec 15 10:45:42 2022 -0800

    redid a few things. should be good now :)

commit 3ee413f379
Author: Godfrey M <godmartinz@gmail.com>
Date:   Thu Dec 15 09:20:30 2022 -0800

    removes livewire stuff

commit b142f8e012
Author: Ivan Nieto Vivanco <inietov@gmail.com>
Date:   Wed Dec 14 23:00:35 2022 -0600

    Add the permission to show purchase cost column to non-admin sessions

commit 418ddcfac3
Merge: c342668f0 1a908e361
Author: snipe <snipe@snipe.net>
Date:   Wed Dec 14 17:46:53 2022 -0800

    Merge pull request #9876 from Toreg87/fixes/locations-deletable

    Fixed #9875: Make locations deletable for non Superuser-Accounts with FullMultipleCompanySupport

commit c342668f0f
Author: snipe <snipe@snipe.net>
Date:   Wed Dec 14 17:25:39 2022 -0800

    Update @scoo73r as a contributor

commit 2f6a26ec7d
Author: snipe <snipe@snipe.net>
Date:   Wed Dec 14 17:25:25 2022 -0800

    Add @scoo73r as a contributor

commit f635278010
Merge: d13a23700 8043b8678
Author: snipe <snipe@snipe.net>
Date:   Wed Dec 14 16:42:41 2022 -0800

    Merge pull request #12251 from snipe/security/upgrade_font_awesome

    Upgraded font awesome to 6.2.1

commit 8043b86786
Author: snipe <snipe@snipe.net>
Date:   Wed Dec 14 16:41:56 2022 -0800

    Upgraded font awesome to 6.2.1

    Signed-off-by: snipe <snipe@snipe.net>

commit d13a237000
Merge: fabefa61b d0d0058e7
Author: snipe <snipe@snipe.net>
Date:   Wed Dec 14 12:13:18 2022 -0800

    Merge pull request #12205 from Godmartinz/sc19675_add_remote_to_importer

    Adds remote field to the user importer

commit b114ffd2c3
Author: akemidx <kojotek.dx@gmail.com>
Date:   Wed Dec 14 14:48:59 2022 -0500

    Grey out button pw reset button for consistency

    When user has no email in their profile, the box is greyed out for
    consistency accross all buttons on the user profile

commit fabefa61b0
Merge: 389ec3a3c f3e57d7dc
Author: snipe <snipe@snipe.net>
Date:   Tue Dec 13 14:00:48 2022 -0800

    Merge pull request #12243 from akemidx/new_grey_out_when_no_assets

    Created method in users.php for adding up all assigned to user and pr…

commit f3e57d7dc0
Author: akemidx <kojotek.dx@gmail.com>
Date:   Tue Dec 13 16:00:59 2022 -0500

    fixing PR

commit 389ec3a3cb
Merge: c432fb9d7 6a72c344b
Author: snipe <snipe@snipe.net>
Date:   Tue Dec 13 12:57:50 2022 -0800

    Merge pull request #12247 from Godmartinz/gh12225_serial_added_to_components

    adds serial to components tab of assets

commit 6a72c344b7
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Dec 13 12:32:30 2022 -0800

    removed the cuddlers

commit 4442b446b9
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Dec 13 10:30:37 2022 -0800

    adds serial to components tab of assets

commit c432fb9d70
Merge: 9e8fff6e5 fa872b09a
Author: snipe <snipe@snipe.net>
Date:   Tue Dec 13 10:28:17 2022 -0800

    Merge pull request #12181 from Godmartinz/gh12163_asset_age

    Adds asset age to asset index and asset view pages

commit 07ae91b00f
Author: akemi <akemi@ShibaPro.local>
Date:   Wed Dec 7 17:46:18 2022 -0500

    Created method in users.php for adding up all assigned to user and providing an integer value. this then used to grey out buttons on user view if user has nothing assigned.

commit 450ad3dcec
Author: Ivan Nieto Vivanco <inietov@gmail.com>
Date:   Mon Dec 12 14:17:08 2022 -0600

    Added the column purchase_cost to user's default view

commit fa872b09a9
Author: Godfrey M <godmartinz@gmail.com>
Date:   Mon Dec 12 10:38:31 2022 -0800

    fixes a typo, the world is great again

commit eb67d1b064
Author: Ivan Nieto Vivanco <inietov@gmail.com>
Date:   Tue Dec 6 18:00:16 2022 -0600

    Filter items from the report if null returned

commit d0d0058e79
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Dec 6 11:19:28 2022 -0800

    removed unwanted changes

commit bbd04f8876
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Dec 6 11:13:24 2022 -0800

    adds the rest of the fields for Remote

commit 36901d271b
Author: Godfrey M <godmartinz@gmail.com>
Date:   Mon Dec 5 16:28:19 2022 -0800

    adds csvmatch for remote. Im a bit lost though lol

commit 3206929ee4
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Nov 29 09:51:42 2022 -0800

    adds AgeFormatter, not working yet

commit 1fe0bfe17e
Author: snipe <snipe@snipe.net>
Date:   Mon Nov 28 19:27:42 2022 -0800

    Removed extra logging case that was very noisy

    Signed-off-by: snipe <snipe@snipe.net>

commit 8d861cfd82
Author: Godfrey M <godmartinz@gmail.com>
Date:   Mon Nov 28 10:59:18 2022 -0800

    adds age to the asset table

commit 078e7281cd
Author: Godfrey M <godmartinz@gmail.com>
Date:   Mon Nov 28 10:45:58 2022 -0800

    adds asset age to asset view

commit f2d4a61e3c
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Oct 18 15:31:37 2022 -0700

    removes dead space

commit 3f25a1bf61
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Oct 18 15:25:38 2022 -0700

    removes dead code

commit f9ac447dd1
Merge: 9b448227f b7bcfaccc
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Oct 18 15:18:09 2022 -0700

    adds default group to LDAP

commit 9b448227f7
Author: Godfrey M <godmartinz@gmail.com>
Date:   Tue Sep 13 11:40:10 2022 -0700

    tinkering to no avail

commit 28bc97f29f
Author: Godfrey M <godmartinz@gmail.com>
Date:   Mon Sep 12 11:40:16 2022 -0700

    one line away from this being over with

commit 193b31e427
Author: Godfrey M <godmartinz@gmail.com>
Date:   Wed Aug 31 12:58:33 2022 -0700

    select options working, testing sync then done

commit 70ac8af9c4
Author: Godfrey M <godmartinz@gmail.com>
Date:   Wed Aug 31 09:53:20 2022 -0700

    .

commit 0c362e8b57
Author: Godfrey M <godmartinz@gmail.com>
Date:   Mon Aug 29 12:09:56 2022 -0700

    gets the groups selector to appear but options are blank

commit fc6fefdb4e
Author: Godfrey M <godmartinz@gmail.com>
Date:   Thu Aug 25 15:19:38 2022 -0700

    adds migration, variables, checkbox,working on groups

commit 1a908e361e
Author: Tobias Regnery <tobias.regnery@gmail.com>
Date:   Thu Jul 29 10:33:34 2021 +0200

    Make locations deletable for non Superuser-Accounts with FullMultipleCompanySupport

    locations->isDeletable() checks via gate::allows if a locations is deletable.
    This calls SnipePermissionsPolicy->before() and checks for !Company::isCurrentUserHasAccess($item).
    This returns false because locations don't have a company_id.

    Check for this and return true if the item don't have a company_id.

Signed-off-by: snipe <snipe@snipe.net>
2022-12-15 15:18:16 -08:00

1151 lines
33 KiB
PHP

<?php
namespace App\Helpers;
use App\Models\Accessory;
use App\Models\Component;
use App\Models\Consumable;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use App\Models\Depreciation;
use App\Models\Setting;
use App\Models\Statuslabel;
use Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
use Image;
use Carbon\Carbon;
class Helper
{
/**
* Simple helper to invoke the markdown parser
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return string
*/
public static function parseEscapedMarkedown($str = null)
{
$Parsedown = new \Parsedown();
$Parsedown->setSafeMode(true);
if ($str) {
return $Parsedown->text($str);
}
}
/**
* The importer has formatted number strings since v3,
* so the value might be a string, or an integer.
* If it's a number, format it as a string.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return string
*/
public static function formatCurrencyOutput($cost)
{
if (is_numeric($cost)) {
if (Setting::getSettings()->digit_separator=='1.234,56') {
return number_format($cost, 2, ',', '.');
}
return number_format($cost, 2, '.', ',');
}
// It's already been parsed.
return $cost;
}
/**
* Static colors for pie charts.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.3]
* @return array
*/
public static function defaultChartColors($index = 0)
{
$colors = [
'#008941',
'#FF4A46',
'#006FA6',
'#A30059',
'#1CE6FF',
'#FFDBE5',
'#7A4900',
'#0000A6',
'#63FFAC',
'#B79762',
'#004D43',
'#8FB0FF',
'#997D87',
'#5A0007',
'#809693',
'#FEFFE6',
'#1B4400',
'#4FC601',
'#3B5DFF',
'#4A3B53',
'#FF2F80',
'#61615A',
'#BA0900',
'#6B7900',
'#00C2A0',
'#FFAA92',
'#FF90C9',
'#B903AA',
'#D16100',
'#DDEFFF',
'#000035',
'#7B4F4B',
'#A1C299',
'#300018',
'#0AA6D8',
'#013349',
'#00846F',
'#372101',
'#FFB500',
'#C2FFED',
'#A079BF',
'#CC0744',
'#C0B9B2',
'#C2FF99',
'#001E09',
'#00489C',
'#6F0062',
'#0CBD66',
'#EEC3FF',
'#456D75',
'#B77B68',
'#7A87A1',
'#788D66',
'#885578',
'#FAD09F',
'#FF8A9A',
'#D157A0',
'#BEC459',
'#456648',
'#0086ED',
'#886F4C',
'#34362D',
'#B4A8BD',
'#00A6AA',
'#452C2C',
'#636375',
'#A3C8C9',
'#FF913F',
'#938A81',
'#575329',
'#00FECF',
'#B05B6F',
'#8CD0FF',
'#3B9700',
'#04F757',
'#C8A1A1',
'#1E6E00',
'#7900D7',
'#A77500',
'#6367A9',
'#A05837',
'#6B002C',
'#772600',
'#D790FF',
'#9B9700',
'#549E79',
'#FFF69F',
'#201625',
'#72418F',
'#BC23FF',
'#99ADC0',
'#3A2465',
'#922329',
'#5B4534',
'#FDE8DC',
'#404E55',
'#0089A3',
'#CB7E98',
'#A4E804',
'#324E72',
'#6A3A4C',
'#83AB58',
'#001C1E',
'#D1F7CE',
'#004B28',
'#C8D0F6',
'#A3A489',
'#806C66',
'#222800',
'#BF5650',
'#E83000',
'#66796D',
'#DA007C',
'#FF1A59',
'#8ADBB4',
'#1E0200',
'#5B4E51',
'#C895C5',
'#320033',
'#FF6832',
'#66E1D3',
'#CFCDAC',
'#D0AC94',
'#7ED379',
'#012C58',
'#7A7BFF',
'#D68E01',
'#353339',
'#78AFA1',
'#FEB2C6',
'#75797C',
'#837393',
'#943A4D',
'#B5F4FF',
'#D2DCD5',
'#9556BD',
'#6A714A',
'#001325',
'#02525F',
'#0AA3F7',
'#E98176',
'#DBD5DD',
'#5EBCD1',
'#3D4F44',
'#7E6405',
'#02684E',
'#962B75',
'#8D8546',
'#9695C5',
'#E773CE',
'#D86A78',
'#3E89BE',
'#CA834E',
'#518A87',
'#5B113C',
'#55813B',
'#E704C4',
'#00005F',
'#A97399',
'#4B8160',
'#59738A',
'#FF5DA7',
'#F7C9BF',
'#643127',
'#513A01',
'#6B94AA',
'#51A058',
'#A45B02',
'#1D1702',
'#E20027',
'#E7AB63',
'#4C6001',
'#9C6966',
'#64547B',
'#97979E',
'#006A66',
'#391406',
'#F4D749',
'#0045D2',
'#006C31',
'#DDB6D0',
'#7C6571',
'#9FB2A4',
'#00D891',
'#15A08A',
'#BC65E9',
'#FFFFFE',
'#C6DC99',
'#203B3C',
'#671190',
'#6B3A64',
'#F5E1FF',
'#FFA0F2',
'#CCAA35',
'#374527',
'#8BB400',
'#797868',
'#C6005A',
'#3B000A',
'#C86240',
'#29607C',
'#402334',
'#7D5A44',
'#CCB87C',
'#B88183',
'#AA5199',
'#B5D6C3',
'#A38469',
'#9F94F0',
'#A74571',
'#B894A6',
'#71BB8C',
'#00B433',
'#789EC9',
'#6D80BA',
'#953F00',
'#5EFF03',
'#E4FFFC',
'#1BE177',
'#BCB1E5',
'#76912F',
'#003109',
'#0060CD',
'#D20096',
'#895563',
'#29201D',
'#5B3213',
'#A76F42',
'#89412E',
'#1A3A2A',
'#494B5A',
'#A88C85',
'#F4ABAA',
'#A3F3AB',
'#00C6C8',
'#EA8B66',
'#958A9F',
'#BDC9D2',
'#9FA064',
'#BE4700',
'#658188',
'#83A485',
'#453C23',
'#47675D',
'#3A3F00',
'#061203',
'#DFFB71',
'#868E7E',
'#98D058',
'#6C8F7D',
'#D7BFC2',
'#3C3E6E',
'#D83D66',
'#2F5D9B',
'#6C5E46',
'#D25B88',
'#5B656C',
'#00B57F',
'#545C46',
'#866097',
'#365D25',
'#252F99',
'#00CCFF',
'#674E60',
'#FC009C',
'#92896B',
];
return $colors[$index];
}
/**
* Increases or decreases the brightness of a color by a percentage of the current brightness.
*
* @param string $hexCode Supported formats: `#FFF`, `#FFFFFF`, `FFF`, `FFFFFF`
* @param float $adjustPercent A number between -1 and 1. E.g. 0.3 = 30% lighter; -0.4 = 40% darker.
*
* @return string
*/
public static function adjustBrightness($hexCode, $adjustPercent)
{
$hexCode = ltrim($hexCode, '#');
if (strlen($hexCode) == 3) {
$hexCode = $hexCode[0].$hexCode[0].$hexCode[1].$hexCode[1].$hexCode[2].$hexCode[2];
}
$hexCode = array_map('hexdec', str_split($hexCode, 2));
foreach ($hexCode as &$color) {
$adjustableLimit = $adjustPercent < 0 ? $color : 255 - $color;
$adjustAmount = ceil($adjustableLimit * $adjustPercent);
$color = str_pad(dechex($color + $adjustAmount), 2, '0', STR_PAD_LEFT);
}
return '#'.implode($hexCode);
}
/**
* Static background (highlight) colors for pie charts
* This is inelegant, and could be refactored later.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.2]
* @return array
*/
public static function chartBackgroundColors()
{
$colors = [
'#f56954',
'#00a65a',
'#f39c12',
'#00c0ef',
'#3c8dbc',
'#d2d6de',
'#3c8dbc',
'#3c8dbc',
'#3c8dbc',
];
return $colors;
}
/**
* Format currency using comma for thousands until local info is property used.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.7]
* @return string
*/
public static function ParseFloat($floatString)
{
/*******
*
* WARNING: This does conversions based on *locale* - a Unix-ey-like thing.
*
* Everything else in the system tends to convert based on the Snipe-IT settings
*
* So it's very likely this is *not* what you want - instead look for the new
*
* ParseCurrency($currencyString)
*
* Which should be directly below here
*
*/
$LocaleInfo = localeconv();
$floatString = str_replace(',', '', $floatString);
$floatString = str_replace($LocaleInfo['decimal_point'], '.', $floatString);
// Strip Currency symbol
// If no currency symbol is set, default to $ because Murica
$currencySymbol = $LocaleInfo['currency_symbol'];
if (empty($currencySymbol)) {
$currencySymbol = '$';
}
$floatString = str_replace($currencySymbol, '', $floatString);
return floatval($floatString);
}
/**
* Format currency using comma or period for thousands, and period or comma for decimal, based on settings.
*
* @author [B. Wetherington] [<bwetherington@grokability.com>]
* @since [v5.2]
* @return Float
*/
public static function ParseCurrency($currencyString) {
$without_currency = str_replace(Setting::getSettings()->default_currency, '', $currencyString); //generally shouldn't come up, since we don't do this in fields, but just in case it does...
if(Setting::getSettings()->digit_separator=='1.234,56') {
//EU format
$without_thousands = str_replace('.', '', $without_currency);
$corrected_decimal = str_replace(',', '.', $without_thousands);
} else {
$without_thousands = str_replace(',', '', $without_currency);
$corrected_decimal = $without_thousands; // decimal is already OK
}
return floatval($corrected_decimal);
}
/**
* Get the list of status labels in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return array
*/
public static function statusLabelList()
{
$statuslabel_list = ['' => trans('general.select_statuslabel')] + Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('deployable', 'desc')
->pluck('name', 'id')->toArray();
return $statuslabel_list;
}
/**
* Get the list of deployable status labels in an array to make a dropdown menu
*
* @todo This should probably be a selectlist, same as the other endpoints
* and we should probably add to the API controllers to make sure that
* the status_id submitted is actually really deployable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.1.0]
* @return array
*/
public static function deployableStatusLabelList()
{
$statuslabel_list = Statuslabel::where('deployable', '=', '1')->orderBy('default_label', 'desc')
->orderBy('name', 'asc')
->orderBy('deployable', 'desc')
->pluck('name', 'id')->toArray();
return $statuslabel_list;
}
/**
* Get the list of status label types in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return array
*/
public static function statusTypeList()
{
$statuslabel_types =
['' => trans('admin/hardware/form.select_statustype')]
+ ['deployable' => trans('admin/hardware/general.deployable')]
+ ['pending' => trans('admin/hardware/general.pending')]
+ ['undeployable' => trans('admin/hardware/general.undeployable')]
+ ['archived' => trans('admin/hardware/general.archived')];
return $statuslabel_types;
}
/**
* Get the list of depreciations in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return array
*/
public static function depreciationList()
{
$depreciation_list = ['' => 'Do Not Depreciate'] + Depreciation::orderBy('name', 'asc')
->pluck('name', 'id')->toArray();
return $depreciation_list;
}
/**
* Get the list of category types in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return array
*/
public static function categoryTypeList()
{
$category_types = [
'' => '',
'accessory' => 'Accessory',
'asset' => 'Asset',
'consumable' => 'Consumable',
'component' => 'Component',
'license' => 'License',
];
return $category_types;
}
/**
* Get the list of custom fields in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return array
*/
public static function customFieldsetList()
{
$customfields = ['' => trans('admin/models/general.no_custom_field')] + CustomFieldset::pluck('name', 'id')->toArray();
return $customfields;
}
/**
* Get the list of custom field formats in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @return array
*/
public static function predefined_formats()
{
$keys = array_keys(CustomField::PREDEFINED_FORMATS);
$stuff = array_combine($keys, $keys);
return $stuff;
}
/**
* Get the list of barcode dimensions
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.3]
* @return array
*/
public static function barcodeDimensions($barcode_type = 'QRCODE')
{
if ($barcode_type == 'C128') {
$size['height'] = '-1';
$size['width'] = '-10';
} elseif ($barcode_type == 'PDF417') {
$size['height'] = '-3';
$size['width'] = '-10';
} else {
$size['height'] = '-3';
$size['width'] = '-3';
}
return $size;
}
/**
* Generates a random string
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return array
*/
public static function generateRandomString($length = 10)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
/**
* This nasty little method gets the low inventory info for the
* alert dropdown
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return array
*/
public static function checkLowInventory()
{
$consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get();
$components = Component::whereNotNull('min_amt')->get();
$avail_consumables = 0;
$items_array = [];
$all_count = 0;
foreach ($consumables as $consumable) {
$avail = $consumable->numRemaining();
if ($avail < ($consumable->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($consumable->qty > 0) {
$percent = number_format((($avail / $consumable->qty) * 100), 0);
} else {
$percent = 100;
}
$items_array[$all_count]['id'] = $consumable->id;
$items_array[$all_count]['name'] = $consumable->name;
$items_array[$all_count]['type'] = 'consumables';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt'] = $consumable->min_amt;
$all_count++;
}
}
foreach ($accessories as $accessory) {
$avail = $accessory->qty - $accessory->users_count;
if ($avail < ($accessory->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($accessory->qty > 0) {
$percent = number_format((($avail / $accessory->qty) * 100), 0);
} else {
$percent = 100;
}
$items_array[$all_count]['id'] = $accessory->id;
$items_array[$all_count]['name'] = $accessory->name;
$items_array[$all_count]['type'] = 'accessories';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt'] = $accessory->min_amt;
$all_count++;
}
}
foreach ($components as $component) {
$avail = $component->numRemaining();
if ($avail < ($component->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($component->qty > 0) {
$percent = number_format((($avail / $component->qty) * 100), 0);
} else {
$percent = 100;
}
$items_array[$all_count]['id'] = $component->id;
$items_array[$all_count]['name'] = $component->name;
$items_array[$all_count]['type'] = 'components';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt'] = $component->min_amt;
$all_count++;
}
}
return $items_array;
}
/**
* Check if the file is an image, so we can show a preview
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param File $file
* @return string | Boolean
*/
public static function checkUploadIsImage($file)
{
$finfo = @finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$filetype = @finfo_file($finfo, $file);
finfo_close($finfo);
if (($filetype == 'image/jpeg') || ($filetype == 'image/jpg') || ($filetype == 'image/png') || ($filetype == 'image/bmp') || ($filetype == 'image/gif')) {
return $filetype;
}
return false;
}
/**
* Walks through the permissions in the permissions config file and determines if
* permissions are granted based on a $selected_arr array.
*
* The $permissions array is a multidimensional array broke down by section.
* (Licenses, Assets, etc)
*
* The $selected_arr should be a flattened array that contains just the
* corresponding permission name and a true or false boolean to determine
* if that group/user has been granted that permission.
*
* @author [A. Gianotto] [<snipe@snipe.net]
* @param array $permissions
* @param array $selected_arr
* @since [v1.0]
* @return array
*/
public static function selectedPermissionsArray($permissions, $selected_arr = [])
{
$permissions_arr = [];
foreach ($permissions as $permission) {
for ($x = 0; $x < count($permission); $x++) {
$permission_name = $permission[$x]['permission'];
if ($permission[$x]['display'] === true) {
if ($selected_arr) {
if (array_key_exists($permission_name, $selected_arr)) {
$permissions_arr[$permission_name] = $selected_arr[$permission_name];
} else {
$permissions_arr[$permission_name] = '0';
}
} else {
$permissions_arr[$permission_name] = '0';
}
}
}
}
return $permissions_arr;
}
/**
* Introspects into the model validation to see if the field passed is required.
* This is used by the blades to add a required class onto the HTML element.
* This isn't critical, but is helpful to keep form fields in sync with the actual
* model level validation.
*
* This does not currently handle form request validation requiredness :(
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return bool
*/
public static function checkIfRequired($class, $field)
{
$rules = $class::rules();
foreach ($rules as $rule_name => $rule) {
if ($rule_name == $field) {
if (strpos($rule, 'required') === false) {
return false;
} else {
return true;
}
}
}
}
/**
* Check to see if the given key exists in the array, and trim excess white space before returning it
*
* @author Daniel Melzter
* @since 3.0
* @param $array array
* @param $key string
* @param $default string
* @return string
*/
public static function array_smart_fetch(array $array, $key, $default = '')
{
array_change_key_case($array, CASE_LOWER);
return array_key_exists(strtolower($key), array_change_key_case($array)) ? e(trim($array[$key])) : $default;
}
/**
* Gracefully handle decrypting encrypted fields (custom fields, etc).
*
* @todo allow this to handle more than just strings (arrays, etc)
*
* @author A. Gianotto
* @since 3.6
* @param CustomField $field
* @param string $string
* @return string
*/
public static function gracefulDecrypt(CustomField $field, $string)
{
if ($field->isFieldDecryptable($string)) {
try {
Crypt::decrypt($string);
return Crypt::decrypt($string);
} catch (DecryptException $e) {
return 'Error Decrypting: '.$e->getMessage();
}
}
return $string;
}
public static function formatStandardApiResponse($status, $payload = null, $messages = null)
{
$array['status'] = $status;
$array['messages'] = $messages;
if (($messages) && (is_array($messages)) && (count($messages) > 0)) {
$array['messages'] = $messages;
}
($payload) ? $array['payload'] = $payload : $array['payload'] = null;
return $array;
}
/*
Possible solution for unicode fieldnames
*/
public static function make_slug($string)
{
return preg_replace('/\s+/u', '_', trim($string));
}
/**
* Return an array (or null) of the the raw and formatted date object for easy use in
* the API and the bootstrap table listings.
*
* @param $date
* @param $type
* @param $array
* @return array|string|null
*/
public static function getFormattedDateObject($date, $type = 'datetime', $array = true)
{
if ($date == '') {
return null;
}
$settings = Setting::getSettings();
/**
* Wrap this in a try/catch so that if Carbon crashes, for example if the $date value
* isn't actually valid, we don't crash out completely.
*
* While this *shouldn't* typically happen since we validate dates before entering them
* into the database (and we use date/datetime fields for native fields in the system),
* it is a possible scenario that a custom field could be created as an "ANY" field, data gets
* added, and then the custom field format gets edited later. If someone put bad data in the
* database before then - or if they manually edited the field's value - it will crash.
*
*/
try {
$tmp_date = new \Carbon($date);
if ($type == 'datetime') {
$dt['datetime'] = $tmp_date->format('Y-m-d H:i:s');
$dt['formatted'] = $tmp_date->format($settings->date_display_format.' '.$settings->time_display_format);
} else {
$dt['date'] = $tmp_date->format('Y-m-d');
$dt['formatted'] = $tmp_date->format($settings->date_display_format);
}
if ($array == 'true') {
return $dt;
}
return $dt['formatted'];
} catch (\Exception $e) {
\Log::warning($e);
return $date.' (Invalid '.$type.' value.)';
}
}
// Nicked from Drupal :)
// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
public static function file_upload_max_size()
{
static $max_size = -1;
if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = self::parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = $post_max_size;
}
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = self::parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
}
return $max_size;
}
public static function file_upload_max_size_readable()
{
static $max_size = -1;
if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = self::parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = ini_get('post_max_size');
}
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = self::parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $post_max_size) {
$max_size = ini_get('upload_max_filesize');
}
}
return $max_size;
}
public static function parse_size($size)
{
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size.
$size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size.
if ($unit) {
// Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
} else {
return round($size);
}
}
public static function filetype_icon($filename)
{
$extension = substr(strrchr($filename, '.'), 1);
$allowedExtensionMap = [
// Images
'jpg' => 'far fa-image',
'jpeg' => 'far fa-image',
'gif' => 'far fa-image',
'png' => 'far fa-image',
// word
'doc' => 'far fa-file-word',
'docx' => 'far fa-file-word',
// Excel
'xls' => 'far fa-file-excel',
'xlsx' => 'far fa-file-excel',
// archive
'zip' => 'fas fa-file-archive',
'rar' => 'fas fa-file-archive',
//Text
'txt' => 'far fa-file-alt',
'rtf' => 'far fa-file-alt',
'xml' => 'far fa-file-alt',
// Misc
'pdf' => 'far fa-file-pdf',
'lic' => 'far fa-save',
];
if ($extension && array_key_exists($extension, $allowedExtensionMap)) {
return $allowedExtensionMap[$extension];
}
return 'far fa-file';
}
public static function show_file_inline($filename)
{
$extension = substr(strrchr($filename, '.'), 1);
if ($extension) {
switch ($extension) {
case 'jpg':
case 'jpeg':
case 'gif':
case 'png':
return true;
break;
default:
return false;
}
}
return false;
}
/**
* Generate a random encrypted password.
*
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @return string
*/
public static function generateEncyrptedPassword(): string
{
return bcrypt(self::generateUnencryptedPassword());
}
/**
* Get a random unencrypted password.
*
* @author Steffen Buehl <sb@sbuehl.com>
*
* @since 5.0.0
*
* @return string
*/
public static function generateUnencryptedPassword(): string
{
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$password = '';
for ($i = 0; $i < 20; $i++) {
$password .= substr($chars, random_int(0, strlen($chars) - 1), 1);
}
return $password;
}
/**
* Process base64 encoded image data and save it on supplied path
*
* @param string $image_data base64 encoded image data with mime type
* @param string $save_path path to a folder where the image should be saved
* @return string path to uploaded image or false if something went wrong
*/
public static function processUploadedImage(String $image_data, String $save_path)
{
if ($image_data == null || $save_path == null) {
return false;
}
// After modification, the image is prefixed by mime info like the following:
// data:image/jpeg;base64,; This causes the image library to be unhappy, so we need to remove it.
$header = explode(';', $image_data, 2)[0];
// Grab the image type from the header while we're at it.
$extension = substr($header, strpos($header, '/') + 1);
// Start reading the image after the first comma, postceding the base64.
$image = substr($image_data, strpos($image_data, ',') + 1);
$file_name = str_random(25).'.'.$extension;
$directory = public_path($save_path);
// Check if the uploads directory exists. If not, try to create it.
if (! file_exists($directory)) {
mkdir($directory, 0755, true);
}
$path = public_path($save_path.$file_name);
try {
Image::make($image)->resize(500, 500, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
} catch (\Exception $e) {
return false;
}
return $file_name;
}
public static function formatFilesizeUnits($bytes)
{
if ($bytes >= 1073741824)
{
$bytes = number_format($bytes / 1073741824, 2) . ' GB';
}
elseif ($bytes >= 1048576)
{
$bytes = number_format($bytes / 1048576, 2) . ' MB';
}
elseif ($bytes >= 1024)
{
$bytes = number_format($bytes / 1024, 2) . ' KB';
}
elseif ($bytes > 1)
{
$bytes = $bytes . ' bytes';
}
elseif ($bytes == 1)
{
$bytes = $bytes . ' byte';
}
else
{
$bytes = '0 bytes';
}
return $bytes;
}
public static function SettingUrls(){
$settings=['#','fields.index', 'statuslabels.index', 'models.index', 'categories.index', 'manufacturers.index', 'suppliers.index', 'departments.index', 'locations.index', 'companies.index', 'depreciations.index'];
return $settings;
}
public static function AgeFormat($date) {
$year = Carbon::parse($date)
->diff(now())->y;
$month = Carbon::parse($date)
->diff(now())->m;
$days = Carbon::parse($date)
->diff(now())->d;
$age='';
if ($year) {
$age .= $year.'y ';
}
if ($month) {
$age .= $month.'m ';
}
if ($days) {
$age .= $days.'d';
}
return $age;
}
}