Compare commits

...

254 Commits

Author SHA1 Message Date
snipe
07e252d58f This runs, but is broken
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 13:36:18 +01:00
snipe
5143b87b3a Revert "Ignore build assets"
This reverts commit a1c85fef14.

Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 11:08:37 +01:00
snipe
b1ef176dbc ¯\_(ツ)_/¯
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 11:08:05 +01:00
snipe
4226642b1b ¯\_(ツ)_/¯
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 11:07:57 +01:00
snipe
e40ba0f79c Set the URLs
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 11:07:48 +01:00
snipe
b8c0279105 Revert "Ignore build assets"
This reverts commit a1c85fef14.
2025-07-28 10:51:16 +01:00
snipe
aae215a968 Updated package.lock
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 10:18:50 +01:00
snipe
bb847b9d99 Renamed vite.config.js to vite.config.jsx
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 10:18:42 +01:00
Shift
a1c85fef14 Ignore build assets 2025-07-28 08:55:52 +00:00
Shift
c65335a61e Add .vue extension to Vue imports 2025-07-28 08:55:52 +00:00
Shift
f95b014d2b Use ES modules 2025-07-28 08:55:51 +00:00
Shift
91e4fddd83 Remove webpack.mix.js 2025-07-28 08:55:51 +00:00
Shift
2af991023d Configure Vite 2025-07-28 08:55:50 +00:00
Shift
a993ab97c6 Update build scripts 2025-07-28 08:55:50 +00:00
Shift
f002c65608 Add npm dependencies 2025-07-28 08:55:50 +00:00
snipe
a7df6fb465 Added DB_SOCKET to example env
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 09:11:00 +01:00
snipe
133e7598e0 Merge pull request #17478 from grokability/library-upgrades
Library upgrades
2025-07-28 09:00:02 +01:00
snipe
c1a52ffa75 Bumped jspdf-autotable from ^3.8.4 to ^5.0.2
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:52:52 +01:00
snipe
4f46313388 Bumped tableexport to ^1.33.0
https://www.npmjs.com/package/tableexport.jquery.plugin
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:50:47 +01:00
snipe
03b2cc9cd2 Dev assets
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:43:22 +01:00
snipe
1a2bf8dc95 Bumped boostrap table from 1.24.1 to 1.24.2
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:43:17 +01:00
snipe
dd63fbeb84 Moved webpack to dev dependencies
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:38:26 +01:00
snipe
59e435c418 Bumped additional libraries
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:36:13 +01:00
snipe
f89f0a19b5 Updated axios
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:33:07 +01:00
snipe
cbc6ef95cb Removed babel-preset
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:26:52 +01:00
snipe
0ceecc9e1d Removed jquery UI
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:24:16 +01:00
snipe
c816902025 Updated postcss
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:19:56 +01:00
snipe
cfb03cdca0 Updated imagemin JS
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:07:34 +01:00
snipe
266f77b08c Update svg-sanitize
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 08:02:54 +01:00
snipe
257d58c236 Moved privacy policy link in settings
Signed-off-by: snipe <snipe@snipe.net>
2025-07-28 03:30:10 +01:00
snipe
015f3d936c Merge pull request #17459 from grokability/#17441-add-status-to-id
Fixed #17441 - hardware listings "remembered" page numbers between statuses
2025-07-24 15:54:33 +01:00
snipe
18d2a0ffd7 Fixed #17441 - added status to table IDs
Signed-off-by: snipe <snipe@snipe.net>
2025-07-24 15:47:26 +01:00
snipe
24afde0e46 Updated hash and minor version
Signed-off-by: snipe <snipe@snipe.net>
2025-07-24 15:35:33 +01:00
snipe
8499faa55a Fixed #17458 - use item_id instead of target_id for user history
Signed-off-by: snipe <snipe@snipe.net>
2025-07-24 15:29:36 +01:00
snipe
c60dd809b8 Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2025-07-24 13:06:57 +01:00
snipe
297b8e33f2 Merge pull request #17436 from Godmartinz/fix-acceptance-markdown
Fixed #17394 - Changes the acceptance letter salutation to target
2025-07-23 22:55:05 +01:00
Godfrey M
b670b2014c accidentally removed a line 2025-07-23 09:56:19 -07:00
Godfrey M
440e969f52 remove unnecessary spacing 2025-07-23 09:47:03 -07:00
snipe
14b79f2f1c Fixed typo in id name
Signed-off-by: snipe <snipe@snipe.net>
2025-07-23 17:00:09 +01:00
snipe
00cf49a61f Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2025-07-23 16:10:47 +01:00
snipe
4f534e0e84 Bumped version/hash
Signed-off-by: snipe <snipe@snipe.net>
2025-07-23 16:02:51 +01:00
snipe
83a19fbbbf Merge pull request #17454 from uberbrady/de_flake_action_log_tests
Enforce order by ID for actionlog tests
2025-07-23 15:06:09 +01:00
snipe
610cb884fc Merge pull request #17452 from uberbrady/de_flake_tls_cert_file_test
This test was flaky, probably due to the PHP statcache.
2025-07-23 15:00:59 +01:00
snipe
ba92cec62b Merge pull request #17453 from grokability/#17316-checkbox-format-on-checkin-checkout
Fixed #17316 - handle checkboxes correctly in checkin/checkout
2025-07-23 14:56:24 +01:00
Brady Wetherington
d92e961a52 enforce order by ID for actionlog tests 2025-07-23 14:55:42 +01:00
snipe
b13e74756a Fixed #17316 - handle checkboxes correctly in checkin/checkout
Signed-off-by: snipe <snipe@snipe.net>
2025-07-23 14:51:34 +01:00
Brady Wetherington
4ef3072766 This test was flaky, probably due to the PHP statcache. 2025-07-23 14:15:52 +01:00
snipe
e96e2461d3 Merge pull request #17450 from grokability/copy-decrypted-custom-fields-to-clipboard
Fixed #17447 - decrypt before copying to clipboard
2025-07-23 12:41:02 +01:00
snipe
7a2e2be169 Fixed #17447 - decrypt before copying to clipboard
Signed-off-by: snipe <snipe@snipe.net>
2025-07-23 12:39:54 +01:00
snipe
8d2a5a7e4a Added location and defaultLoc to searchable relations in audit log
Signed-off-by: snipe <snipe@snipe.net>
2025-07-23 12:28:23 +01:00
snipe
b7b0e4fab5 Merge pull request #17447 from Godmartinz/make-custom-fields-copyable
Adds #17133 Copy ability to all Custom fields
2025-07-23 12:11:47 +01:00
Godfrey M
a624a79b30 add terenary 2025-07-22 16:36:19 -07:00
Godfrey M
313135da6f Merge branch 'develop' into make-custom-fields-copyable 2025-07-22 16:26:57 -07:00
Godfrey M
58d27d1247 move copy button to front 2025-07-22 16:17:52 -07:00
snipe
edfb28168f Merge pull request #17446 from marcusmoore/snipe-it-17445-move-jobtitle-under-assigned_to-in-assettransformer
Fixed #17445 - move jobtitle under assigned_to in AssetTransformer
2025-07-22 20:27:01 +01:00
Godfrey M
8d0e03bb06 fix copy target 2025-07-22 11:57:46 -07:00
Marcus Moore
855f6f77cf Re-add sorting 2025-07-22 11:49:32 -07:00
Godfrey M
6236cffe14 adds copy links for filled custom fields 2025-07-22 11:49:11 -07:00
Marcus Moore
322a71fbb8 Add jobtitleFormatter 2025-07-22 11:37:34 -07:00
Marcus Moore
4d9f8476f3 Update field key in AssetPresenter 2025-07-22 11:07:58 -07:00
Marcus Moore
d7d93b14b2 Move jobtitle under assigned_to 2025-07-22 11:02:26 -07:00
snipe
d1af3ece6e One more tweak to login checkbox
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 15:25:09 +01:00
snipe
8153b20984 Check for demo mode on UI for able to login
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 15:18:34 +01:00
snipe
a50f605c29 Merge pull request #17443 from grokability/added-not-allowed-cursor
Adds disabled cursor on uneditable fields in user create/edit
2025-07-22 15:13:14 +01:00
snipe
daf23edd10 Adds disabled cursor on uneditable fields in user create/edit
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 15:10:27 +01:00
snipe
2eaaeb8259 Merge pull request #17423 from grokability/tighter-permissions-on-non-admins
Tighter permissions on non-admins and demo modes
2025-07-22 14:32:50 +01:00
snipe
a02c62d62c Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 14:12:51 +01:00
snipe
e0232a8e84 Renamed gate
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 14:02:18 +01:00
snipe
6ea5693b2f Updated comment, removed log error statement
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 13:59:58 +01:00
snipe
030c2114d1 Merge pull request #17442 from grokability/user-api-eula-fix
Fixed FD-49886 - Optimize user queries
2025-07-22 13:39:36 +01:00
snipe
2cb18e3668 Remove fields from query - eulas was querying actionlogs
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 13:25:41 +01:00
snipe
cd9f8be563 Optimize for when we already have the counts
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 13:25:16 +01:00
snipe
a02792e9bf Merge pull request #17300 from uberbrady/add_actionlog_tests
Fixed #17071 - Adding various tests of the contents of ActionLogs for lots of events
2025-07-22 10:51:30 +01:00
snipe
41bb422244 Merge pull request #17439 from marcusmoore/component-file-test-fix
Attempt to fix flaky file upload tests pt2
2025-07-21 23:16:03 +01:00
Marcus Moore
54663d3342 Pass order to api in test 2025-07-21 15:10:35 -07:00
snipe
2529f7369f Merge pull request #17438 from grokability/file-upload-tests-fix
Attempt to fix flaky file upload tests
2025-07-21 22:48:38 +01:00
snipe
909c33dccf Fixed order location
Signed-off-by: snipe <snipe@snipe.net>
2025-07-21 22:45:17 +01:00
snipe
1adc9f1aa9 Attempt to fix flaky tests
Signed-off-by: snipe <snipe@snipe.net>
2025-07-21 22:18:15 +01:00
Godfrey M
49da9e58fd changed markdown to point to assignedto name 2025-07-21 12:00:00 -07:00
snipe
f3e288d078 Updated language strings
Signed-off-by: snipe <snipe@snipe.net>
2025-07-21 17:46:49 +01:00
snipe
988000952e Fixed RB-3997
Signed-off-by: snipe <snipe@snipe.net>
2025-07-21 13:48:01 +01:00
snipe
6537f3794b Merge pull request #17292 from Godmartinz/fail_with_inputs
FIXED: #17194 Return to bulk edit with errors and inputs
2025-07-21 12:03:52 +01:00
snipe
d31718ba8a Merge pull request #17389 from grokability/use-transformer-for-api-asset-model-response
Use standard model transformer for asset model API response
2025-07-21 11:52:25 +01:00
snipe
9dd4bc5fa8 Merge pull request #17391 from Godmartinz/add-components-notifications
FIXED: #13844 Adds Webhook and Mail Notifications for Components
2025-07-21 11:51:30 +01:00
snipe
df5f1bd522 Merge pull request #17434 from grokability/dependabot/github_actions/develop/codacy/codacy-analysis-cli-action-4.4.7
Bump codacy/codacy-analysis-cli-action from 4.4.5 to 4.4.7
2025-07-21 11:45:04 +01:00
dependabot[bot]
ddffab9169 Bump codacy/codacy-analysis-cli-action from 4.4.5 to 4.4.7
Bumps [codacy/codacy-analysis-cli-action](https://github.com/codacy/codacy-analysis-cli-action) from 4.4.5 to 4.4.7.
- [Release notes](https://github.com/codacy/codacy-analysis-cli-action/releases)
- [Commits](https://github.com/codacy/codacy-analysis-cli-action/compare/v4.4.5...v4.4.7)

---
updated-dependencies:
- dependency-name: codacy/codacy-analysis-cli-action
  dependency-version: 4.4.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 09:26:25 +00:00
snipe
0c34073582 Namespace fix for presenter
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 17:17:04 +01:00
snipe
14674947cb Fixed test namespace
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 17:15:51 +01:00
snipe
51bccdbd66 Merge pull request #17424 from marcusmoore/chore/livewire-ugprade
Bumped livewire to v3.6.4
2025-07-18 17:12:14 +01:00
snipe
f0fbb3cf36 Uncomment permissions test
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 16:31:31 +01:00
Brady Wetherington
0cc47aacbe Got tests to pass by making them match our current reality, rather than wishes 2025-07-18 16:14:32 +01:00
snipe
fafd592290 Wrap groups and activated into the other canEditAuthFields gate
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 16:03:43 +01:00
snipe
40e754b8c3 Additional criteria for the canEditAuthFields gate
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 16:03:22 +01:00
snipe
483301db7a Changed some of the gating logic for demo mode. Sigh.
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 16:02:59 +01:00
snipe
218606fbd6 Updated view permissions
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 16:02:41 +01:00
snipe
c601b8e62c Updated test
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 16:02:11 +01:00
snipe
2bd68ec991 Uncommented importer gate
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 13:17:25 +01:00
snipe
66842648ed Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 13:17:10 +01:00
snipe
ce54b9a7b5 Removed duplicate alert
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 13:16:59 +01:00
Brady Wetherington
8a5f6d2a5d Refactor base test into Trait, clean test output for easier comparison 2025-07-18 13:16:35 +01:00
snipe
1d86a5476f Updated language
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 12:45:43 +01:00
snipe
ca4d3f6bce Changed gate name, removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2025-07-18 12:45:32 +01:00
Godfrey M
2812f2ce92 remove log 2025-07-17 15:04:42 -07:00
Godfrey M
5c623db798 fix redirect 2025-07-17 14:57:00 -07:00
Marcus Moore
edaf005fe1 Bump livewire to v3.6.4 2025-07-17 14:15:10 -07:00
snipe
4f6e407247 More consistent language degarding the demo
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 21:13:13 +01:00
snipe
e30881239c A few more clean ups for demo mode
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 21:08:50 +01:00
snipe
bbde2cc4b2 Use history blade component
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 21:04:11 +01:00
snipe
16d18c79d7 Fixed email editable field
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 21:03:20 +01:00
snipe
a0d2cb8a03 Clearer (if longer) gate name
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:47:20 +01:00
snipe
1bb5dc7e69 Added one more test
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:40:01 +01:00
Brady Wetherington
58759acfe4 Think I hit _all_ of the tests we need to mess with here 2025-07-17 20:15:01 +01:00
snipe
0cd5136052 Added translations
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:12:52 +01:00
snipe
b3c6fe5369 Use both new gates in user edit
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:12:46 +01:00
snipe
599718f84e Use new gates in controllers
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:12:32 +01:00
snipe
d9a5452388 Defined new gates
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:12:10 +01:00
snipe
0fe49e04bf Attempt to use a gate here?
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:09:27 +01:00
snipe
a98d3fb4dc Check for the format of the permissions (string, object, array)
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:09:17 +01:00
Godfrey M
8c670d1832 clean up 2025-07-17 12:08:49 -07:00
snipe
c232f490bc Show user log
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:08:40 +01:00
snipe
c7280953dd Added/updated tests
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 20:08:32 +01:00
Godfrey M
8f4c606c64 remove var dumps 2025-07-17 12:04:33 -07:00
Godfrey M
6740afab42 radio buttons values return correctly 2025-07-17 11:59:09 -07:00
Godfrey M
5df22b3e6a checkboxes properly check 2025-07-17 11:56:52 -07:00
snipe
3d9d18a0d5 Fixed weird CSS quirk
Signed-off-by: snipe <snipe@snipe.net>
2025-07-17 19:22:23 +01:00
Godfrey M
fc469707a3 clean up 2025-07-16 10:51:33 -07:00
snipe
77fdc370c7 Merge pull request #17415 from uberbrady/clean_unaccepted_assets_report
[FD-47386, FD-49095] New Artisan command to clean checkout acceptances
2025-07-16 17:34:49 +01:00
snipe
301290fb6d Send emails on acceptance even if signature is not required
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 17:02:04 +01:00
snipe
07fffe2f79 Merge pull request #17410 from grokability/remove-password-from-welcome
Remove password from welcome email, prompt for reset instead
2025-07-16 16:54:07 +01:00
snipe
0227a63fa5 Slightly clearer language
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 16:31:45 +01:00
snipe
27764b863c Updated language
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 16:25:36 +01:00
snipe
032fd75f9e Added default invite password token timeout
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 16:23:51 +01:00
snipe
0bf4f861f3 Nicer debugging
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 16:23:25 +01:00
snipe
fd8f90cb52 Added new password broker for longer toekn lifetime
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 16:23:11 +01:00
snipe
b6c6b025c8 Added expiry language
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 16:20:26 +01:00
snipe
3d89e98d1f Small tweaks to welcome email blade
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 16:20:15 +01:00
Brady Wetherington
7c5110ed5d Add more action logs tests everywhere I can think of it. 2025-07-16 16:20:06 +01:00
Brady Wetherington
0a474f48ad WIP: Adding various tests of the contents of ActionLogs for lots of events 2025-07-16 16:20:06 +01:00
Brady Wetherington
c409bfd5be New Artisan command to clean checkout acceptances and a migration that runs it 2025-07-16 16:06:23 +01:00
snipe
39d5d5b2e0 Merge branch 'develop' into remove-password-from-welcome 2025-07-16 15:05:13 +01:00
snipe
8a80d9009d Refomatted hidden array
Signed-off-by: snipe <snipe@snipe.net>
2025-07-16 12:24:48 +01:00
Godfrey M
f62b5df566 use ternaries instead of optionals 2025-07-15 15:40:21 -07:00
Godfrey M
214757ab0b fix mailable 2025-07-15 12:04:36 -07:00
Godfrey M
f130186b37 add Component Checkin Mail 2025-07-15 11:56:34 -07:00
Godfrey M
2244eebc3b add Component Checkout Mail 2025-07-15 11:00:39 -07:00
snipe
4176792f2d Translate field
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 16:32:17 +01:00
snipe
1e6cef52c9 Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 15:17:08 +01:00
snipe
a0f4f30a50 Added try/catch
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 15:13:33 +01:00
snipe
4cbf6ac393 Re-add /setup crential email
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:20:13 +01:00
snipe
af7425d8e6 Remove unused variable
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:19:12 +01:00
snipe
3fea909d3f Removed send credentials option from user controller
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:14:10 +01:00
snipe
7c37d40677 Use plaintext in the database so that the password will never be valid
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:13:50 +01:00
snipe
3a97c27350 Removed logging
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:13:29 +01:00
snipe
e0516a52a8 Formatting change
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:12:55 +01:00
snipe
a85ec6efb3 Set token in welcome email constructor
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:12:42 +01:00
snipe
3795c74814 Added string
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:12:26 +01:00
snipe
27954dc6d3 Use password reset token
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:12:18 +01:00
snipe
68c4187a09 Removed email creds option from user create
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:11:15 +01:00
snipe
b9834231f3 Remove email credentials chexkbox
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 14:08:36 +01:00
snipe
2be343ea1c More specific no password
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 13:11:45 +01:00
snipe
109fe1b62c Use no password as temp password
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 13:11:18 +01:00
snipe
63d691a63c Removed noisy log
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 13:10:48 +01:00
snipe
6f57d6b876 Merge pull request #17407 from grokability/fixes-signature-pad-chrome
Fixed display of acceptance button if signature is not required
2025-07-15 10:58:34 +01:00
snipe
e0bad99ea1 Fixes display of acceptannce button if signature is not required
Signed-off-by: snipe <snipe@snipe.net>
2025-07-15 10:55:30 +01:00
snipe
e39eb09cfb Merge pull request #17390 from Godmartinz/unhandled-redirect-error
FIXED redirect option being NULL
2025-07-10 19:41:40 +01:00
Godfrey M
64d397c3f3 add component notification tests 2025-07-10 11:26:10 -07:00
Godfrey M
465ac1d1e1 remove ternary 2025-07-10 08:39:13 -07:00
Godfrey M
18d6becebc populate other_redirect in store method 2025-07-10 08:36:15 -07:00
snipe
943a4093ad Use standard model transformer for asset model API response
Signed-off-by: snipe <snipe@snipe.net>
2025-07-10 15:42:39 +01:00
snipe
b0917a5131 Merge pull request #17385 from grokability/17383-fix-api-route-path
Fixed #17383 - re-add `/hardware/` as an object type in the file upload API
2025-07-10 13:10:43 +01:00
snipe
0972c4e340 Re-added /hardware/ as viable route for API file uploads
Signed-off-by: snipe <snipe@snipe.net>
2025-07-10 13:06:22 +01:00
Godfrey M
3bbd0fdbcd google notifications fires properly 2025-07-09 17:02:51 -07:00
snipe
43a237bf95 Merge pull request #17378 from grokability/phpcs/models
Code formatting fixes
2025-07-09 21:55:30 +01:00
snipe
95f867b267 Code formatting fixes
Signed-off-by: snipe <snipe@snipe.net>
2025-07-09 21:48:53 +01:00
snipe
e96daf469a Better phrasing
Signed-off-by: snipe <snipe@snipe.net>
2025-07-09 21:00:54 +01:00
snipe
f2cdfe9e47 Normalize textarea for notes in acceptance form
Signed-off-by: snipe <snipe@snipe.net>
2025-07-09 20:58:07 +01:00
snipe
929b67e768 Merge pull request #17376 from grokability/small-tweak-to-acceptance-ui
Better indicate via submit button colors and messaging that something is about to be accepted or declined
2025-07-09 20:21:50 +01:00
snipe
0573dc136a Put the sig check back
Signed-off-by: snipe <snipe@snipe.net>
2025-07-09 20:16:30 +01:00
snipe
48588f6a9e Small UI sugar on the acceptance/signature screen
Signed-off-by: snipe <snipe@snipe.net>
2025-07-09 20:08:19 +01:00
Godfrey M
8214b11da5 MS teams fires properly 2025-07-09 11:44:53 -07:00
Godfrey M
36090bf83e checked in notification fires, updated icon translation usage 2025-07-09 11:35:24 -07:00
Godfrey M
bffb2fe82f checkout notification fires 2025-07-09 11:23:27 -07:00
Godfrey M
500cbf5d92 add component checkout notification, update checkout blade, update listener 2025-07-09 11:12:18 -07:00
snipe
88579b9bf3 Merge pull request #17374 from uberbrady/improve_inline_videos
Fixed [FD-49538 ] - use a Video tag for video files for non-Safari usage
2025-07-09 15:47:19 +01:00
snipe
e8bb9bde99 Fixed #8201 - splits first_name and last_name in user export
Signed-off-by: snipe <snipe@snipe.net>
2025-07-09 15:46:42 +01:00
Brady Wetherington
0ee3cca4da Use a Video tag for video files for non-Safari usage 2025-07-09 15:15:53 +01:00
snipe
f89ee6b7f2 Merge pull request #17361 from Godmartinz/return-custom-textarea_input
Fixed #7957 - custom field Textarea input not retaining when switching Asset Models with shared fields
2025-07-08 22:02:07 +01:00
snipe
aebfb52c85 Merge pull request #17362 from Godmartinz/license-redirect-bug
Fixed #17310 - 500 on redirect when checking in a license seat
2025-07-08 21:59:22 +01:00
Godfrey M
667bd7af0e fix checkout_to_type being null when checking in 2025-07-08 13:53:10 -07:00
snipe
bbf69bc582 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2025-07-08 21:26:15 +01:00
snipe
f2b7a3d002 Updated language strings
Signed-off-by: snipe <snipe@snipe.net>
2025-07-08 21:25:31 +01:00
Godfrey M
3fd9e3ab56 include textareas input return 2025-07-08 12:02:56 -07:00
snipe
8e11466a54 Added query scope
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 22:09:23 +01:00
snipe
dade9797d5 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 21:46:13 +01:00
snipe
97c1e65ffc Fixed fieldname
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 20:58:26 +01:00
snipe
b4e22f4a21 Small fix for seat listing
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 20:56:26 +01:00
snipe
58b6feb3ca Merge pull request #17356 from grokability/show-only-taken-licenses
[FD-49569 ] - Show only assigned in license tab
2025-07-07 17:05:38 +01:00
snipe
41c4920d45 Show only assigned in license tab
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 16:58:36 +01:00
snipe
d1ddd8de98 Re-add column selector
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 16:23:48 +01:00
snipe
f41307eb4a Merge pull request #17353 from grokability/fixes-#14295-send-acceptance-on-signing
Fixed #14295 - allow user to receive an email PDF upon signing
2025-07-07 15:59:03 +01:00
snipe
59de77feb0 Use company name if provided instead of site name
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 15:55:40 +01:00
snipe
8ebbcf6e80 Removed console commands
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 15:55:31 +01:00
snipe
24c6e836dd Added checkbox toggle
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 15:51:24 +01:00
snipe
8e38b3898e Fixes #14295 - allow user to receive an email PDF upon signing
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 15:38:36 +01:00
snipe
ce9a5e35c9 Merge pull request #17352 from grokability/fixed-#17273-notes-in-upcoming-audit
Fixed #17273 -  switch to HTML table from markdown
2025-07-07 14:42:43 +01:00
snipe
b092779697 Fixed #17273 - switch to HTML table from markdown
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 14:37:38 +01:00
snipe
ab30a96d16 Merge pull request #17327 from Godmartinz/asset_model_redirect
FIXED: #15861 adds a redirect option for asset model and previous page
2025-07-07 14:00:31 +01:00
snipe
dab0fb16ad Merge pull request #17291 from Godmartinz/fix_bulk_checkout_focus
Fixes #12094 - Adds focus to select2 in bulk checkout
2025-07-07 13:57:12 +01:00
snipe
5be398bc99 Merge pull request #17350 from grokability/tighter-control-on-company
Fixes #17302 - Tighter control on company
2025-07-07 13:45:08 +01:00
snipe
fe4172957f Merge pull request #17351 from grokability/smaller-pdfs
Fixed #17349 - enable_font_subsetting in PDFs
2025-07-07 13:33:29 +01:00
snipe
ff3a59d347 Fixed #17349 - enable_font_subsetting in PDFs
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 13:32:25 +01:00
snipe
f9aedea26f Eager load admin
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 13:21:07 +01:00
snipe
5abd2c7151 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 13:12:16 +01:00
snipe
bfcaf4f37b Removed unecessary use statement
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 12:36:59 +01:00
snipe
5f4e1835bc Removed unused method
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 12:36:16 +01:00
snipe
c1f1ae6b64 Removed logging
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 12:31:12 +01:00
snipe
c4fcc6c24e Removed direct scoping calls
Signed-off-by: snipe <snipe@snipe.net>
2025-07-07 12:26:30 +01:00
snipe
dd73ad9941 Merge pull request #17341 from Godmartinz/query_error_rb19824
Fixed #17193: perform Orderby before Collection in Bulk Assets Controller
2025-07-07 11:19:37 +01:00
snipe
ac21f7569f Merge pull request #17346 from grokability/add-video-uploads
[FD-49538] Add video/audio uploads
2025-07-07 11:15:19 +01:00
snipe
4ef0158da4 Use preview instead of image text
Signed-off-by: snipe <snipe@snipe.net>
2025-07-03 20:19:29 +01:00
snipe
4db3b3ba0e Use config array for extensions in restore tool
Signed-off-by: snipe <snipe@snipe.net>
2025-07-03 20:19:13 +01:00
snipe
dc43d85323 Check for audio files
Signed-off-by: snipe <snipe@snipe.net>
2025-07-03 20:15:30 +01:00
snipe
62651f381c Expand safe allowed inline files
Signed-off-by: snipe <snipe@snipe.net>
2025-07-03 20:13:57 +01:00
snipe
3e9098907a Use config file for file types/mimes
Signed-off-by: snipe <snipe@snipe.net>
2025-07-03 20:11:31 +01:00
snipe
e18df250f8 Removed console debugging
Signed-off-by: snipe <snipe@snipe.net>
2025-07-03 20:08:08 +01:00
Godfrey M
be5c5a51da get desired behavior of select-2 2025-07-02 11:20:04 -07:00
Godfrey M
a728fad675 perform orderBy on query before converting to a Collection 2025-07-02 11:06:35 -07:00
snipe
185629b310 Merge pull request #17338 from grokability/small-depreciation-tweaks
Fixed #1909 - Small depreciation tweaks
2025-07-02 18:37:21 +01:00
snipe
30ebea4f2d Return int count
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 18:24:27 +01:00
snipe
b135c1eac2 Updated language strings in view
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 18:15:06 +01:00
snipe
88fef73d6f Use new translation
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 17:54:10 +01:00
snipe
556a9039e9 New strings
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 17:53:55 +01:00
snipe
cdfe6c21c1 Tightened HTML, added translations
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 17:53:42 +01:00
snipe
b094ebdd66 Removed validation of > 0
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 17:53:32 +01:00
snipe
526a7ddea6 Merge pull request #17337 from grokability/fixes-#17112-ldap-location-set-to-0
Fixed #17112 - Set location ID to null instead of 0
2025-07-02 17:20:34 +01:00
snipe
bb5ad31cba Merge pull request #17336 from uberbrady/safer_deserialize
Use safer deserialization defaults
2025-07-02 17:15:48 +01:00
snipe
549da2efed Set location ID to null instead of 0
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 17:15:18 +01:00
snipe
e5e586dc43 Attempt to generalize companyable in company scope
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 17:12:55 +01:00
Brady Wetherington
8a682beb0e Use safer deserialization defaults 2025-07-02 14:49:12 +01:00
snipe
699e9f75c9 Fixed RB-19892
Check for location before trying to grab company property

Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 11:57:42 +01:00
snipe
759e30977b Merge pull request #17333 from grokability/fixes-#17326-dash-sorting
Fixed #17326 - sorting on dashboard
2025-07-02 11:43:48 +01:00
snipe
6cfdb49cc3 Fixed #17326 - sorting on dashboard
Signed-off-by: snipe <snipe@snipe.net>
2025-07-02 11:41:21 +01:00
snipe
1195121bf0 Merge pull request #17330 from uberbrady/add_escaping_to_action_logs
Add escaping to user_agent and remote_ip variables for API results
2025-07-01 23:30:41 +01:00
Brady Wetherington
8bc067b18b Add escaping to user_agent and remote_ip variables for API results 2025-07-01 23:22:09 +01:00
Godfrey M
76f59f7b85 fix variables 2025-07-01 12:52:16 -07:00
Godfrey M
55ebb4671f update check in and check out controllers 2025-07-01 12:44:26 -07:00
Godfrey M
8a9cf07063 editing controllers and edit blades for other categories 2025-07-01 12:31:55 -07:00
Godfrey M
ca9ff8cf19 set return type for RedirectOptions 2025-07-01 12:04:02 -07:00
Godfrey M
7217d9c427 adds redirect to previous page, use match instead of switch cases 2025-07-01 11:55:46 -07:00
Godfrey M
9d712ad8f1 clean up code 2025-07-01 10:56:02 -07:00
Godfrey M
f3e49e7010 add asset model as a redirect option 2025-07-01 10:43:00 -07:00
Godfrey M
c8b213c190 remove some changes, move error bag 2025-06-24 13:10:32 -07:00
Godfrey M
942de9dce5 got validation to redirect back to form and display 2025-06-24 12:42:07 -07:00
Godfrey M
483f684b04 adds focus to select 2 bulk checkout 2025-06-24 09:58:38 -07:00
622 changed files with 12849 additions and 12802 deletions

View File

@@ -28,6 +28,7 @@ PUBLIC_FILESYSTEM_DISK=local_public
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=db
DB_SOCKET=null
DB_PORT='3306'
DB_DATABASE=snipeit
DB_USERNAME=snipeit
@@ -168,6 +169,7 @@ AWS_DEFAULT_REGION=null
LOGIN_MAX_ATTEMPTS=5
LOGIN_LOCKOUT_DURATION=60
RESET_PASSWORD_LINK_EXPIRES=900
INVITE_PASSWORD_LINK_EXPIRES=1500
# --------------------------------------------
# OPTIONAL: MISC

View File

@@ -24,6 +24,7 @@ PUBLIC_FILESYSTEM_DISK=local_public
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_SOCKET=null
DB_PORT=3306
DB_DATABASE=null
DB_USERNAME=null
@@ -174,6 +175,7 @@ LOGIN_AUTOCOMPLETE=false
RESET_PASSWORD_LINK_EXPIRES=15
PASSWORD_CONFIRM_TIMEOUT=10800
PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN=50
INVITE_PASSWORD_LINK_EXPIRES=1500
# --------------------------------------------
# OPTIONAL: MISC

View File

@@ -36,7 +36,7 @@ jobs:
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@v4.4.5
uses: codacy/codacy-analysis-cli-action@v4.4.7
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations

View File

@@ -0,0 +1,68 @@
<?php
namespace App\Console\Commands;
use App\Models\CheckoutAcceptance;
use App\Models\LicenseSeat;
use App\Models\User;
use Illuminate\Console\Command;
class CleanIncorrectCheckoutAcceptances extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:clean-checkout-acceptances';
/**
* The console command description.
*
* @var string
*/
protected $description = "Delete checkout acceptances for checkouts to non-users";
/**
* Execute the console command.
*/
public function handle()
{
$deletions = 0;
$skips = 0;
// This walks *every* checkoutacceptance. That's gnarly. But necessary
$this->withProgressBar(CheckoutAcceptance::all(), function ($checkoutAcceptance) use (&$deletions, &$skips) {
$item = $checkoutAcceptance->checkoutable;
$checkout_to_id = $checkoutAcceptance->assigned_to_id;
if(is_null($item)) {
$this->info("'Checkoutable' Item is null, going to next record");
return; //'false' allegedly breaks execution entirely, so 'true' maybe doesn't? hrm. just straight return maybe?
}
if(get_class($item) == LicenseSeat::class) {
$item = $item->license;
}
foreach($item->assetlog()->where('action_type','checkout')->get() as $assetlog) {
if ($assetlog->target_id == $checkout_to_id && $assetlog->target_type != User::class) {
//We have a checkout-to an ID for a non-User, which matches to an ID in the checkout_acceptances table
//now, let's compare the _times_ - are they close?
//I'm picking `created_at` over `action_date` because I'm more interested in when the actionlogs
//were _created_, not when they were alleged to have happened - those created_at times need to be within 'X' seconds of
//each other (currently 5)
if ($assetlog->created_at->diffInSeconds($checkoutAcceptance->created_at, true) <= 5) { //we're allowing for five _ish_ seconds of slop
$deletions++;
$checkoutAcceptance->forceDelete(); // HARD delete this record; it should have never been
return;
} else {
//$this->info("The two records are too far apart");
}
} else {
//$this->info("No match! checkout to id: " . $checkout_to_id." target_id: ".$assetlog->target_id." target_type: ".$assetlog->target_type);
}
}
$skips++;
});
$this->error("Final deletion count: $deletions, and skip count: $skips");
}
}

View File

@@ -182,7 +182,7 @@ class LdapSync extends Command
// Inject location information fields
for ($i = 0; $i < $results['count']; $i++) {
$results[$i]['ldap_location_override'] = false;
$results[$i]['location_id'] = 0;
$results[$i]['location_id'] = null;
}
// Grab subsets based on location-specific DNs, and overwrite location for these users.

View File

@@ -329,9 +329,9 @@ class RestoreFromBackup extends Command
}
}
}
$good_extensions = ['png', 'gif', 'jpg', 'svg', 'jpeg', 'doc', 'docx', 'pdf', 'txt',
'zip', 'rar', 'xls', 'xlsx', 'lic', 'xml', 'rtf', 'webp', 'key', 'ico', 'avif'
];
$good_extensions = config('filesystems.allowed_upload_extensions_array');
foreach (array_merge($private_files, $public_files) as $file) {
$has_wildcard = (strpos($file, '*') !== false);
if ($has_wildcard) {

View File

@@ -133,8 +133,17 @@ class Handler extends ExceptionHandler
// This is traaaaash but it handles models that are not found while using route model binding :(
// The only alternative is to set that at *each* route, which is crazypants
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
$ids = method_exists($e, 'getIds') ? $e->getIds() : [];
// This gets the MVC model name from the exception and formats in a way that's less fugly
if (in_array('bulkedit', $ids, true)) {
$error_array = session()->get('bulk_asset_errors');
return redirect()
->route('hardware.bulkedit')
->withErrors($error_array, 'bulk_asset_errors')
->withInput();
}
// This gets the MVC model name from the exception and formats in a way that's less fugly
$model_name = strtolower(implode(" ", preg_split('/(?=[A-Z])/', last(explode('\\', $e->getModel())))));
$route = str_plural(strtolower(last(explode('\\', $e->getModel())))).'.index';

View File

@@ -13,6 +13,7 @@ use App\Models\Setting;
use App\Models\Statuslabel;
use App\Models\License;
use App\Models\Location;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
use Carbon\Carbon;
@@ -876,6 +877,48 @@ class Helper
return false;
}
/**
* Check if the file is a video, so we can show a preview
*
* @param File $file
* @return string | Boolean
* @author [B. Wetherington] [<bwetherington@grokability.com>]
* @since [v8.1.18]
*/
public static function checkUploadIsVideo($file)
{
$finfo = @finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$filetype = @finfo_file($finfo, $file);
finfo_close($finfo);
if (($filetype == 'video/mp4') || ($filetype == 'video/quicktime') || ($filetype == 'video/mpeg') || ($filetype == 'video/ogg') || ($filetype == 'video/webm') || ($filetype == 'video/x-msvide')) {
return $filetype;
}
return false;
}
/**
* Check if the file is audio, so we can show a preview
*
* @param File $file
* @return string | Boolean
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
*/
public static function checkUploadIsAudio($file)
{
$finfo = @finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$filetype = @finfo_file($finfo, $file);
finfo_close($finfo);
if (($filetype == 'audio/mpeg') || ($filetype == 'audio/ogg')) {
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.
@@ -1170,6 +1213,15 @@ class Helper
// Misc
'pdf' => 'far fa-file-pdf',
'lic' => 'far fa-save',
// video
'mov' => 'fa-solid fa-video',
'mp4' => 'fa-solid fa-video',
// audio
'ogg' => 'fa-solid fa-file-audio',
'mp3' => 'fa-solid fa-file-audio',
'wav' => 'fa-solid fa-file-audio',
];
if ($extension && array_key_exists($extension, $allowedExtensionMap)) {
@@ -1480,68 +1532,64 @@ class Helper
}
static public function getRedirectOption($request, $id, $table, $item_id = null)
static public function getRedirectOption($request, $id, $table, $item_id = null) : RedirectResponse
{
$redirect_option = Session::get('redirect_option');
$checkout_to_type = Session::get('checkout_to_type');
$redirect_option = Session::get('redirect_option') ?? $request->redirect_option;
$checkout_to_type = Session::get('checkout_to_type') ?? null;
$checkedInFrom = Session::get('checkedInFrom');
$other_redirect = Session::get('other_redirect');
$backUrl = Session::pull('back_url', route('home'));
// return to previous page
if ($redirect_option === 'back') {
if ($backUrl === route('home')) {
return redirect()->to($backUrl)
->with('warning', trans('general.page_error'));
}
return redirect()->to($backUrl);
}
// return to index
if ($redirect_option == 'index') {
switch ($table) {
case "Assets":
return route('hardware.index');
case "Users":
return route('users.index');
case "Licenses":
return route('licenses.index');
case "Accessories":
return route('accessories.index');
case "Components":
return route('components.index');
case "Consumables":
return route('consumables.index');
}
return match ($table) {
'Assets' => redirect()->route('hardware.index'),
'Users' => redirect()->route('users.index'),
'Licenses' => redirect()->route('licenses.index'),
'Accessories' => redirect()->route('accessories.index'),
'Components' => redirect()->route('components.index'),
'Consumables' => redirect()->route('consumables.index'),
};
}
// return to thing being assigned
if ($redirect_option == 'item') {
switch ($table) {
case "Assets":
return route('hardware.show', $id ?? $item_id);
case "Users":
return route('users.show', $id ?? $item_id);
case "Licenses":
return route('licenses.show', $id ?? $item_id);
case "Accessories":
return route('accessories.show', $id ?? $item_id);
case "Components":
return route('components.show', $id ?? $item_id);
case "Consumables":
return route('consumables.show', $id ?? $item_id);
}
return match ($table) {
'Assets' => redirect()->route('hardware.show', $id ?? $item_id),
'Users' => redirect()->route('users.show', $id ?? $item_id),
'Licenses' => redirect()->route('licenses.show', $id ?? $item_id),
'Accessories' => redirect()->route('accessories.show', $id ?? $item_id),
'Components' => redirect()->route('components.show', $id ?? $item_id),
'Consumables' => redirect()->route('consumables.show', $id ?? $item_id),
};
}
// return to assignment target
if ($redirect_option == 'target') {
switch ($checkout_to_type) {
case 'user':
return route('users.show', $request->assigned_user ?? $checkedInFrom);
case 'location':
return route('locations.show', $request->assigned_location ?? $checkedInFrom);
case 'asset':
return route('hardware.show', $request->assigned_asset ?? $checkedInFrom);
}
return match ($checkout_to_type) {
'user' => redirect()->route('users.show', $request->assigned_user ?? $checkedInFrom),
'location' => redirect()->route('locations.show', $request->assigned_location ?? $checkedInFrom),
'asset' => redirect()->route('hardware.show', $request->assigned_asset ?? $checkedInFrom),
};
}
// return to somewhere else
if ($redirect_option == 'other_redirect') {
switch ($other_redirect) {
case 'audit':
return route('assets.audit.due');
}
return match ($other_redirect) {
'audit' => redirect()->route('assets.audit.due'),
'model' => redirect()->route('models.show', $request->model_id),
};
}

View File

@@ -41,15 +41,21 @@ class StorageHelper
{
$allowed_inline = [
'pdf',
'svg',
'jpg',
'gif',
'svg',
'avif',
'webp',
'png',
'gif',
'gif',
'jpg',
'mov',
'mp3',
'mp4',
'ogg',
'pdf',
'png',
'svg',
'svg',
'wav',
'webm',
'webp',
];

View File

@@ -83,7 +83,8 @@ class AccessoriesController extends Controller
// Was the accessory created?
if ($accessory->save()) {
// Redirect to the new accessory page
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.create.success'));
return Helper::getRedirectOption($request, $accessory->id, 'Accessories')
->with('success', trans('admin/accessories/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
@@ -167,7 +168,8 @@ class AccessoriesController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($accessory->save()) {
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.update.success'));
return Helper::getRedirectOption($request, $accessory->id, 'Accessories')
->with('success', trans('admin/accessories/message.update.success'));
}
} else {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));

View File

@@ -78,7 +78,8 @@ class AccessoryCheckinController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.checkin.success'));
return Helper::getRedirectOption($request, $accessory->id, 'Accessories')
->with('success', trans('admin/accessories/message.checkin.success'));
}
// Redirect to the accessory management page with error
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error'));

View File

@@ -97,7 +97,7 @@ class AccessoryCheckoutController extends Controller
// Redirect to the new accessory page
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))
return Helper::getRedirectOption($request, $accessory->id, 'Accessories')
->with('success', trans('admin/accessories/message.checkout.success'));
}
}

View File

@@ -21,6 +21,7 @@ use App\Models\License;
use App\Models\Component;
use App\Models\Consumable;
use App\Notifications\AcceptanceAssetAcceptedNotification;
use App\Notifications\AcceptanceAssetAcceptedToUserNotification;
use App\Notifications\AcceptanceAssetDeclinedNotification;
use Exception;
use Illuminate\Http\Request;
@@ -151,6 +152,8 @@ class AcceptanceController extends Controller
}
}
$assigned_user = User::find($acceptance->assigned_to_id);
// this is horrible
switch($acceptance->checkoutable_type){
case 'App\Models\Asset':
@@ -160,35 +163,30 @@ class AcceptanceController extends Controller
return redirect()->back()->with('error', trans('admin/models/message.does_not_exist'));
}
$display_model = $asset_model->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
case 'App\Models\Accessory':
$pdf_view_route ='account.accept.accept-accessory-eula';
$accessory = Accessory::find($item->id);
$display_model = $accessory->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
case 'App\Models\LicenseSeat':
$pdf_view_route ='account.accept.accept-license-eula';
$license = License::find($item->license_id);
$display_model = $license->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
case 'App\Models\Component':
$pdf_view_route ='account.accept.accept-component-eula';
$component = Component::find($item->id);
$display_model = $component->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
case 'App\Models\Consumable':
$pdf_view_route ='account.accept.accept-consumable-eula';
$consumable = Consumable::find($item->id);
$display_model = $consumable->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
}
// if ($acceptance->checkoutable_type == 'App\Models\Asset') {
@@ -229,7 +227,7 @@ class AcceptanceController extends Controller
'note' => $request->input('note'),
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
'assigned_to' => $assigned_to,
'assigned_to' => $assigned_user->present()->fullName,
'company_name' => $branding_settings->site_name,
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
'logo' => $path_logo,
@@ -243,6 +241,19 @@ class AcceptanceController extends Controller
}
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
// Send the PDF to the signing user
if (($request->input('send_copy') == '1') && ($assigned_user->email !='')) {
// Add the attachment for the signing user into the $data array
$data['file'] = $pdf_filename;
try {
$assigned_user->notify(new AcceptanceAssetAcceptedToUserNotification($data));
} catch (\Exception $e) {
Log::warning($e);
}
}
try {
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
} catch (\Exception $e) {

View File

@@ -154,7 +154,7 @@ class AssetModelsController extends Controller
$assetmodel = $request->handleImages($assetmodel);
if ($assetmodel->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new AssetModelsTransformer)->transformAssetModel($assetmodel), trans('admin/models/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
@@ -207,7 +207,7 @@ class AssetModelsController extends Controller
$assetmodel = AssetModel::findOrFail($id);
$assetmodel->fill($request->all());
$assetmodel = $request->handleImages($assetmodel);
/**
* Allow custom_fieldset_id to override and populate fieldset_id.
* This is stupid, but required for legacy API support.
@@ -222,7 +222,7 @@ class AssetModelsController extends Controller
if ($assetmodel->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.update.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new AssetModelsTransformer)->transformAssetModel($assetmodel), trans('admin/models/message.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));

View File

@@ -43,7 +43,10 @@ class CompaniesController extends Controller
$companies = Company::withCount(['assets as assets_count' => function ($query) {
$query->AssetsForShow();
}])->withCount('licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
}])
->with('adminuser')
->withCount('licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
if ($request->filled('search')) {
$companies->TextSearch($request->input('search'));
@@ -119,6 +122,7 @@ class CompaniesController extends Controller
{
$this->authorize('view', Company::class);
$company = Company::findOrFail($id);
$this->authorize('view', $company);
return (new CompaniesTransformer)->transformCompany($company);
}
@@ -136,6 +140,7 @@ class CompaniesController extends Controller
{
$this->authorize('update', Company::class);
$company = Company::findOrFail($id);
$this->authorize('update', $company);
$company->fill($request->all());
$company = $request->handleImages($company);
@@ -188,6 +193,7 @@ class CompaniesController extends Controller
'companies.image',
]);
if ($request->filled('search')) {
$companies = $companies->where('companies.name', 'LIKE', '%'.$request->get('search').'%');
}

View File

@@ -29,6 +29,15 @@ class LicenseSeatsController extends Controller
$seats = LicenseSeat::with('license', 'user', 'asset', 'user.department')
->where('license_seats.license_id', $licenseId);
if ($request->input('status') == 'available') {
$seats->whereNull('license_seats.assigned_to');
}
if ($request->input('status') == 'assigned') {
$seats->ByAssigned();
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
if ($request->input('sort') == 'department') {

View File

@@ -33,6 +33,7 @@ class UploadedFilesController extends Controller
'assets' => Asset::class,
'components' => Component::class,
'consumables' => Consumable::class,
'hardware' => Asset::class,
'licenses' => License::class,
'locations' => Location::class,
'models' => AssetModel::class,
@@ -44,6 +45,7 @@ class UploadedFilesController extends Controller
'assets' => 'private_uploads/assets/',
'components' => 'private_uploads/components/',
'consumables' => 'private_uploads/consumables/',
'hardware' => 'private_uploads/assets/',
'licenses' => 'private_uploads/licenses/',
'locations' => 'private_uploads/locations/',
'models' => 'private_uploads/assetmodels/',
@@ -55,6 +57,7 @@ class UploadedFilesController extends Controller
'assets' => 'asset',
'components' => 'component',
'consumables' => 'consumable',
'hardware' => 'asset',
'licenses' => 'license',
'locations' => 'location',
'models' => 'model',
@@ -90,6 +93,7 @@ class UploadedFilesController extends Controller
'id',
'filename',
'action_type',
'action_date',
'note',
'created_at',
];

View File

@@ -23,6 +23,7 @@ use App\Notifications\CurrentInventory;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;
@@ -81,7 +82,12 @@ class UsersController extends Controller
'users.autoassign_licenses',
'users.website',
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations', 'eulas')
])->with('manager')
->with('groups')
->with('userloc')
->with('company')
->with('department')
->with('createdBy')
->withCount([
'assets as assets_count' => function(Builder $query) {
$query->withoutTrashed();
@@ -475,8 +481,25 @@ class UsersController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
}
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
// check for permissions related fields and pull them out if the current user cannot edit them
if (auth()->user()->can('canEditAuthFields', $user) && auth()->user()->can('editableOnDemo')) {
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
if ($request->filled('username')) {
$user->username = $request->input('username');
}
if ($request->filled('email')) {
$user->email = $request->input('email');
}
if ($request->filled('activated')) {
$user->activated = $request->input('activated');
}
}
// We need to use has() instead of filled()

View File

@@ -153,7 +153,8 @@ class AssetCheckinController extends Controller
if ($asset->save()) {
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))->with('success', trans('admin/hardware/message.checkin.success'));
return Helper::getRedirectOption($request, $asset->id, 'Assets')
->with('success', trans('admin/hardware/message.checkin.success'));
}
// Redirect to the asset management page with error
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());

View File

@@ -123,7 +123,7 @@ class AssetCheckoutController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
return Helper::getRedirectOption($request, $asset->id, 'Assets')
->with('success', trans('admin/hardware/message.checkout.success'));
}
// Redirect to the asset management page with error

View File

@@ -227,24 +227,27 @@ class AssetsController extends Controller
}
}
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
session()->put(['redirect_option' => $request->get('redirect_option'),
'checkout_to_type' => $request->get('checkout_to_type'),
'other_redirect' => 'model' ]);
if ($successes) {
if ($failures) {
//some succeeded, some failed
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) //FIXME - not tested
return Helper::getRedirectOption($request, $asset->id, 'Assets') //FIXME - not tested
->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)]))
->with('warning', trans_choice('admin/hardware/message.create.partial_failure', $failures, ['failures' => join("; ", $failures)]));
} else {
if (count($successes) == 1) {
//the most common case, keeping it so we don't have to make every use of that translation string be trans_choice'ed
//and re-translated
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
return Helper::getRedirectOption($request, $asset->id, 'Assets')
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset), 'id', 'tag' => e($asset->asset_tag)]));
} else {
//multi-success
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
return Helper::getRedirectOption($request, $asset->id, 'Assets')
->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)]));
}
}
@@ -265,6 +268,7 @@ class AssetsController extends Controller
public function edit(Asset $asset) : View | RedirectResponse
{
$this->authorize($asset);
session()->put('back_url', url()->previous());
return view('hardware/edit')
->with('item', $asset)
->with('statuslabel_list', Helper::statusLabelList())
@@ -427,11 +431,15 @@ class AssetsController extends Controller
}
}
}
session()->put([
'redirect_option' => $request->get('redirect_option'),
'checkout_to_type' => $request->get('checkout_to_type'),
'other_redirect' => $request->get('redirect_option') === 'other_redirect' ? 'model' : null,
]);
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
if ($asset->save()) {
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
return Helper::getRedirectOption($request, $asset->id, 'Assets')
->with('success', trans('admin/hardware/message.update.success'));
}
@@ -996,7 +1004,7 @@ class AssetsController extends Controller
}
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name, $originalValues);
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))->with('success', trans('admin/hardware/message.audit.success'));
return Helper::getRedirectOption($request, $asset->id, 'Assets')->with('success', trans('admin/hardware/message.audit.success'));
}
return redirect()->back()->withInput()->withErrors($asset->getErrors());

View File

@@ -112,11 +112,47 @@ class BulkAssetsController extends Controller
// This handles all of the pivot sorting below (versus the assets.* fields in the allowed_columns array)
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.id';
$assets = Asset::with('assignedTo', 'location', 'model')
$query = Asset::with('assignedTo', 'location', 'model')
->whereIn('assets.id', $asset_ids)
->withTrashed();
$assets = $assets->get();
switch ($sort_override) {
case 'model':
$query->OrderModels($order);
break;
case 'model_number':
$query->OrderModelNumber($order);
break;
case 'category':
$query->OrderCategory($order);
break;
case 'manufacturer':
$query->OrderManufacturer($order);
break;
case 'company':
$query->OrderCompany($order);
break;
case 'location':
$query->OrderLocation($order);
break;
case 'rtd_location':
$query->OrderRtdLocation($order);
break;
case 'status_label':
$query->OrderStatus($order);
break;
case 'supplier':
$query->OrderSupplier($order);
break;
case 'assigned_to':
$query->OrderAssigned($order);
break;
default:
$query->orderBy($column_sort, $order);
break;
}
$assets = $query->get();
if ($assets->isEmpty()) {
Log::debug('No assets were found for the provided IDs', ['ids' => $asset_ids]);
@@ -125,6 +161,7 @@ class BulkAssetsController extends Controller
$models = $assets->unique('model_id');
$modelNames = [];
foreach($models as $model) {
$modelNames[] = $model->model->name;
}
@@ -160,7 +197,6 @@ class BulkAssetsController extends Controller
case 'edit':
$this->authorize('update', Asset::class);
return view('hardware/bulk')
->with('assets', $asset_ids)
->with('statuslabel_list', Helper::statusLabelList())
@@ -169,40 +205,7 @@ class BulkAssetsController extends Controller
}
}
switch ($sort_override) {
case 'model':
$assets->OrderModels($order);
break;
case 'model_number':
$assets->OrderModelNumber($order);
break;
case 'category':
$assets->OrderCategory($order);
break;
case 'manufacturer':
$assets->OrderManufacturer($order);
break;
case 'company':
$assets->OrderCompany($order);
break;
case 'location':
$assets->OrderLocation($order);
case 'rtd_location':
$assets->OrderRtdLocation($order);
break;
case 'status_label':
$assets->OrderStatus($order);
break;
case 'supplier':
$assets->OrderSupplier($order);
break;
case 'assigned_to':
$assets->OrderAssigned($order);
break;
default:
$assets->orderBy($column_sort, $order);
break;
}
return redirect()->back()->with('error', 'No action selected');
}
@@ -221,11 +224,8 @@ class BulkAssetsController extends Controller
$error_array = array();
// Get the back url from the session and then destroy the session
$bulk_back_url = route('hardware.index');
if ($request->session()->has('bulk_back_url')) {
$bulk_back_url = $request->session()->pull('bulk_back_url');
}
$bulk_back_url = $request->session()->pull('bulk_back_url', url()->previous());
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
@@ -540,7 +540,13 @@ class BulkAssetsController extends Controller
} // end asset foreach
if ($has_errors > 0) {
return redirect($bulk_back_url)->with('bulk_asset_errors', $error_array);
session()->put('bulkedit_ids', $request->input('ids'));
session()->put('bulk_asset_errors',$error_array);
return redirect()
->route('hardware.bulkedit')
->with('bulk_asset_errors', $error_array)
->withInput();
}
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
@@ -732,4 +738,33 @@ class BulkAssetsController extends Controller
}
return false;
}
public function bulkEditForm(): View|RedirectResponse
{
$this->authorize('update', Asset::class);
$asset_ids = session()->pull('bulkedit_ids', []);
if (empty($asset_ids)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.no_assets_selected'));
}
$assets = Asset::with('model')->withTrashed()->whereIn('id', $asset_ids)->get();
if ($assets->isEmpty()) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.assets_do_not_exist_or_are_invalid'));
}
$models = $assets->unique('model_id');
$modelNames = [];
foreach ($models as $model) {
$modelNames[] = $model->model->name;
}
return view('hardware/bulk')
->with('assets', $asset_ids)
->with('statuslabel_list', Helper::statusLabelList())
->with('models', $models->pluck(['model']))
->with('modelNames', $modelNames);
}
}

View File

@@ -123,11 +123,13 @@ final class CompaniesController extends Controller
*/
public function destroy($companyId) : RedirectResponse
{
if (is_null($company = Company::find($companyId))) {
return redirect()->route('companies.index')
->with('error', trans('admin/companies/message.not_found'));
}
$this->authorize('delete', $company);
if (! $company->isDeletable()) {
return redirect()->route('companies.index')

View File

@@ -100,8 +100,8 @@ class ComponentCheckinController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success',
trans('admin/components/message.checkin.success'));
return Helper::getRedirectOption($request, $component->id, 'Components')
->with('success', trans('admin/components/message.checkin.success'));
}
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));

View File

@@ -120,6 +120,7 @@ class ComponentCheckoutController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success', trans('admin/components/message.checkout.success'));
return Helper::getRedirectOption($request, $component->id, 'Components')
->with('success', trans('admin/components/message.checkout.success'));
}
}

View File

@@ -91,7 +91,8 @@ class ComponentsController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($component->save()) {
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success', trans('admin/components/message.create.success'));
return Helper::getRedirectOption($request, $component->id, 'Components')
->with('success', trans('admin/components/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($component->getErrors());
@@ -111,6 +112,7 @@ class ComponentsController extends Controller
{
$this->authorize('update', $component);
session()->put('back_url', url()->previous());
return view('components/edit')
->with('item', $component)
->with('category_type', 'component');
@@ -164,7 +166,8 @@ class ComponentsController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($component->save()) {
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success', trans('admin/components/message.update.success'));
return Helper::getRedirectOption($request, $component->id, 'Components')
->with('success', trans('admin/components/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($component->getErrors());

View File

@@ -111,6 +111,7 @@ class ConsumableCheckoutController extends Controller
// Redirect to the new consumable page
return redirect()->to(Helper::getRedirectOption($request, $consumable->id, 'Consumables'))->with('success', trans('admin/consumables/message.checkout.success'));
return Helper::getRedirectOption($request, $consumable->id, 'Consumables')
->with('success', trans('admin/consumables/message.checkout.success'));
}
}

View File

@@ -90,7 +90,8 @@ class ConsumablesController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($consumable->save()) {
return redirect()->to(Helper::getRedirectOption($request, $consumable->id, 'Consumables'))->with('success', trans('admin/consumables/message.create.success'));
return Helper::getRedirectOption($request, $consumable->id, 'Consumables')
->with('success', trans('admin/consumables/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($consumable->getErrors());
@@ -107,6 +108,7 @@ class ConsumablesController extends Controller
public function edit(Consumable $consumable) : View | RedirectResponse
{
$this->authorize($consumable);
session()->put('back_url', url()->previous());
return view('consumables/edit')
->with('item', $consumable)
->with('category_type', 'consumable');
@@ -160,7 +162,8 @@ class ConsumablesController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($consumable->save()) {
return redirect()->to(Helper::getRedirectOption($request, $consumable->id, 'Consumables'))->with('success', trans('admin/consumables/message.update.success'));
return Helper::getRedirectOption($request, $consumable->id, 'Consumables')
->with('success', trans('admin/consumables/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($consumable->getErrors());

View File

@@ -98,14 +98,17 @@ class LicenseCheckinController extends Controller
$licenseSeat->notes = $request->input('notes');
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($request->get('redirect_option') === 'target'){
session()->put(['checkout_to_type' => 'user']);
}
// Was the asset updated?
if ($licenseSeat->save()) {
event(new CheckoutableCheckedIn($licenseSeat, $return_to, auth()->user(), $request->input('notes')));
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.checkin.success'));
return Helper::getRedirectOption($request, $license->id, 'Licenses')
->with('success', trans('admin/licenses/message.checkin.success'));
}
// Redirect to the license page with error

View File

@@ -89,7 +89,8 @@ class LicenseCheckoutController extends Controller
if ($checkoutTarget) {
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.checkout.success'));
return Helper::getRedirectOption($request, $license->id, 'Licenses')
->with('success', trans('admin/licenses/message.checkout.success'));
}

View File

@@ -105,7 +105,8 @@ class LicensesController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($license->save()) {
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.create.success'));
return Helper::getRedirectOption($request, $license->id, 'Licenses')
->with('success', trans('admin/licenses/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($license->getErrors());
@@ -125,7 +126,7 @@ class LicensesController extends Controller
{
$this->authorize('update', $license);
session()->put('back_url', url()->previous());
$maintained_list = [
'' => 'Maintained',
'1' => 'Yes',
@@ -181,7 +182,8 @@ class LicensesController extends Controller
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($license->save()) {
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.update.success'));
return Helper::getRedirectOption($request, $license->id, 'Licenses')
->with('success', trans('admin/licenses/message.update.success'));
}
// If we can't adjust the number of seats, the error is flashed to the session by the event handler in License.php
return redirect()->back()->withInput()->withErrors($license->getErrors());

View File

@@ -13,15 +13,8 @@ use App\Models\Company;
use App\Models\Group;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\WelcomeNotification;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Storage;
use Redirect;
use Str;
use Symfony\Component\HttpFoundation\StreamedResponse;
use App\Notifications\CurrentInventory;
@@ -130,7 +123,7 @@ class UsersController extends Controller
}
$user->permissions = json_encode($permissions_array);
// we have to invoke the
// we have to invoke the form request here to handle image uploads
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
session()->put(['redirect_option' => $request->get('redirect_option')]);
@@ -142,19 +135,8 @@ class UsersController extends Controller
$user->groups()->sync([]);
}
if (($request->input('email_user') == 1) && ($request->filled('email'))) {
// Send the credentials through email
$data = [];
$data['email'] = e($request->input('email'));
$data['username'] = e($request->input('username'));
$data['first_name'] = e($request->input('first_name'));
$data['last_name'] = e($request->input('last_name'));
$data['password'] = e($request->input('password'));
$user->notify(new WelcomeNotification($data));
}
return redirect()->to(Helper::getRedirectOption($request, $user->id, 'Users'))->with('success', trans('admin/users/message.success.create'));
return Helper::getRedirectOption($request, $user->id, 'Users')
->with('success', trans('admin/users/message.success.create'));
}
return redirect()->back()->withInput()->withErrors($user->getErrors());
@@ -186,6 +168,7 @@ class UsersController extends Controller
{
$this->authorize('update', User::class);
session()->put('back_url', url()->previous());
$user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($user->id);
if ($user) {
@@ -246,20 +229,14 @@ class UsersController extends Controller
}
}
// Only save groups if the user is a superuser
if (auth()->user()->isSuperUser()) {
$user->groups()->sync($request->input('groups'));
}
// Update the user fields
$user->username = trim($request->input('username'));
$user->email = trim($request->input('email'));
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
$user->locale = $request->input('locale');
$user->employee_num = $request->input('employee_num');
$user->activated = $request->input('activated', 0);
$user->jobtitle = $request->input('jobtitle', null);
$user->phone = $request->input('phone');
$user->location_id = $request->input('location_id', null);
@@ -271,8 +248,6 @@ class UsersController extends Controller
$user->city = $request->input('city', null);
$user->state = $request->input('state', null);
$user->country = $request->input('country', null);
// if a user is editing themselves we should always keep activated true
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
$user->zip = $request->input('zip', null);
$user->remote = $request->input('remote', 0);
$user->vip = $request->input('vip', 0);
@@ -281,30 +256,49 @@ class UsersController extends Controller
$user->end_date = $request->input('end_date', null);
$user->autoassign_licenses = $request->input('autoassign_licenses', 0);
// Set this here so that we can overwrite it later if the user is an admin or superadmin
$user->activated = $request->input('activated', auth()->user()->is($user) ? 1 : $user->activated);
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)
->update(['location_id' => $request->input('location_id', null)]);
// Do we want to update the user password?
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
// check for permissions related fields and only set them if the user has permission to edit them
if (auth()->user()->can('canEditAuthFields', $user) && auth()->user()->can('editableOnDemo')) {
$user->username = trim($request->input('username'));
$user->email = trim($request->input('email'));
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
// Do we want to update the user password?
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
$permissions_array = $request->input('permission');
// Strip out the superuser permission if the user isn't a superadmin
if (! auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
$permissions_array['superuser'] = $orig_superuser;
}
$user->permissions = json_encode($permissions_array);
// Only save groups if the user is a superuser
if (auth()->user()->isSuperUser()) {
$user->groups()->sync($request->input('groups'));
}
}
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)
->update(['location_id' => $user->location_id]);
$permissions_array = $request->input('permission');
// Strip out the superuser permission if the user isn't a superadmin
if (! auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
$permissions_array['superuser'] = $orig_superuser;
}
$user->permissions = json_encode($permissions_array);
// Handle uploaded avatar
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
@@ -312,7 +306,7 @@ class UsersController extends Controller
if ($user->save()) {
// Redirect to the user page
return redirect()->to(Helper::getRedirectOption($request, $user->id, 'Users'))
return Helper::getRedirectOption($request, $user->id, 'Users')
->with('success', trans('admin/users/message.success.update'));
}
return redirect()->back()->withInput()->withErrors($user->getErrors());
@@ -510,6 +504,8 @@ class UsersController extends Controller
trans('admin/companies/table.title'),
trans('admin/users/table.title'),
trans('general.employee_number'),
trans('admin/users/table.first_name'),
trans('admin/users/table.last_name'),
trans('admin/users/table.name'),
trans('admin/users/table.username'),
trans('admin/users/table.email'),
@@ -555,6 +551,8 @@ class UsersController extends Controller
($user->company) ? $user->company->name : '',
$user->jobtitle,
$user->employee_num,
$user->first_name,
$user->last_name,
$user->present()->fullName(),
$user->username,
$user->email,

View File

@@ -31,7 +31,7 @@ class UploadFileRequest extends Request
$max_file_size = Helper::file_upload_max_size();
return [
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,json,webp,avif|max:'.$max_file_size,
'file.*' => 'required|mimes:'.config('filesystems.allowed_upload_extensions_for_validator').'|max:'.$max_file_size,
];
}
@@ -80,9 +80,20 @@ class UploadFileRequest extends Request
{
$attributes = [];
if ($this->file) {
if (($this->file) && (is_array($this->file))) {
for ($i = 0; $i < count($this->file); $i++) {
$attributes['file.'.$i] = $this->file[$i]->getClientOriginalName();
try {
if ($this->file[$i]) {
$attributes['file.'.$i] = $this->file[$i]->getClientOriginalName();
}
} catch (\Exception $e) {
$attributes['file.'.$i] = 'Invalid file';
}
}
}

View File

@@ -113,8 +113,8 @@ class ActionlogsTransformer
// Display the changes if the user is an admin or superadmin
if (Gate::allows('admin')) {
$clean_meta[$fieldname]['old'] = ($enc_old) ? unserialize($enc_old): '';
$clean_meta[$fieldname]['new'] = ($enc_new) ? unserialize($enc_new): '';
$clean_meta[$fieldname]['old'] = ($enc_old) ? unserialize($enc_old, ['allowed_classes' => false]) : '';
$clean_meta[$fieldname]['new'] = ($enc_new) ? unserialize($enc_new, ['allowed_classes' => false]) : '';
}
}
@@ -198,8 +198,8 @@ class ActionlogsTransformer
'note' => ($actionlog->note) ? Helper::parseEscapedMarkedownInline($actionlog->note): null,
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta: null,
'remote_ip' => ($actionlog->remote_ip) ?? null,
'user_agent' => ($actionlog->user_agent) ?? null,
'remote_ip' => e($actionlog->remote_ip) ?? null,
'user_agent' => e($actionlog->user_agent) ?? null,
'action_source' => ($actionlog->action_source) ?? null,
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime'): Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
];

View File

@@ -80,7 +80,6 @@ class AssetsTransformer
'qr' => ($setting->qr_code=='1') ? config('app.url').'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png' : null,
'alt_barcode' => ($setting->alt_barcode_enabled=='1') ? config('app.url').'/uploads/barcodes/'.str_slug($setting->alt_barcode).'-'.str_slug($asset->asset_tag).'.png' : null,
'assigned_to' => $this->transformAssignedTo($asset),
'jobtitle' => $asset->assigned ? e($asset->assigned->jobtitle) : null,
'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months.' '.trans('admin/hardware/form.months')) : null,
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
'created_by' => ($asset->adminuser) ? [
@@ -204,6 +203,7 @@ class AssetsTransformer
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
'email'=> ($asset->assigned->email) ? e($asset->assigned->email) : null,
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
'jobtitle' => $asset->assigned->jobtitle ? e($asset->assigned->jobtitle) : null,
'type' => 'user',
] : null;
}

View File

@@ -26,11 +26,11 @@ class DepreciationsTransformer
$array = [
'id' => (int) $depreciation->id,
'name' => e($depreciation->name),
'months' => $depreciation->months.' '.trans('general.months'),
'months' => trans_choice('general.months_plural', $depreciation->months),
'depreciation_min' => $depreciation->depreciation_type === 'percent' ? $depreciation->depreciation_min.'%' : $depreciation->depreciation_min,
'assets_count' => $depreciation->assets_count,
'models_count' => $depreciation->models_count,
'licenses_count' => $depreciation->licenses_count,
'assets_count' => ($depreciation->assets_count > 0) ? (int) $depreciation->assets_count : 0,
'models_count' => ($depreciation->models_count > 0) ? (int) $depreciation->models_count : 0,
'licenses_count' => ($depreciation->licenses_count > 0) ? (int) $depreciation->licenses_count : 0,
'created_by' => ($depreciation->adminuser) ? [
'id' => (int) $depreciation->adminuser->id,
'name'=> e($depreciation->adminuser->present()->fullName()),

View File

@@ -133,7 +133,7 @@ abstract class Importer
} else {
$this->csv = Reader::createFromString($file);
}
$this->tempPassword = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 40);
$this->tempPassword = '*** NO PASSWORD - IMPORTED VIA CSV ***';
}
// Cached Values for import lookups

View File

@@ -7,7 +7,9 @@ use App\Models\Department;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\WelcomeNotification;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Password;
/**
* This is ONLY used for the User Import. When we are importing users
@@ -80,6 +82,7 @@ class UserImporter extends ItemImporter
$this->item['username'] = $user_formatted_array['username'];
}
// Check if a numeric ID was passed. If it does, use that above all else.
if ((array_key_exists('id', $this->item) && ($this->item['id'] != "") && (is_numeric($this->item['id'])))) {
$user = User::find($this->item['id']);
@@ -89,12 +92,25 @@ class UserImporter extends ItemImporter
if ($user) {
// If the user does not want to update existing values, only add new ones, bail out
if (! $this->updating) {
Log::debug('A matching User '.$this->item['name'].' already exists. ');
return;
}
$this->log('Updating User');
// Todo - check that this works
if (!Gate::allows('canEditAuthFields', $user)) {
unset($user->username);
unset($user->email);
unset($user->password);
unset($user->activated);
}
$user->update($this->sanitizeItemForUpdating($user));
// Why do we have to do this twice? Update should
$user->save();
// Update the location of any assets checked out to this user
@@ -110,28 +126,32 @@ class UserImporter extends ItemImporter
// This needs to be applied after the update logic, otherwise we'll overwrite user passwords
// Issue #5408
$this->item['password'] = bcrypt($this->tempPassword);
$this->item['password'] = $this->tempPassword;
$this->log('No matching user, creating one');
$user = new User();
$user->created_by = auth()->id();
$user->fill($this->sanitizeItemForStoring($user));
// TODO - check for gate here I guess
if ($user->save()) {
$this->log('User '.$this->item['name'].' was created');
if (($user->email) && ($user->activated == '1')) {
$data = [
'email' => $user->email,
'username' => $user->username,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'password' => $this->tempPassword,
];
if ($this->send_welcome) {
$user->notify(new WelcomeNotification($data));
try {
$user->notify(new WelcomeNotification($user));
} catch (\Exception $e) {
Log::warning('Could not send welcome notification for user: ' . $e->getMessage());
}
}
}
$user = null;
$this->item = null;
@@ -140,9 +160,9 @@ class UserImporter extends ItemImporter
}
$this->logError($user, 'User');
return;
}
/**
* Fetch an existing department, or create new if it doesn't exist
*

View File

@@ -4,10 +4,12 @@ namespace App\Listeners;
use App\Events\CheckoutableCheckedOut;
use App\Mail\CheckinAccessoryMail;
use App\Mail\CheckinComponentMail;
use App\Mail\CheckinLicenseMail;
use App\Mail\CheckoutAccessoryMail;
use App\Mail\CheckoutAssetMail;
use App\Mail\CheckinAssetMail;
use App\Mail\CheckoutComponentMail;
use App\Mail\CheckoutConsumableMail;
use App\Mail\CheckoutLicenseMail;
use App\Models\Accessory;
@@ -22,9 +24,11 @@ use App\Models\Setting;
use App\Models\User;
use App\Notifications\CheckinAccessoryNotification;
use App\Notifications\CheckinAssetNotification;
use App\Notifications\CheckinComponentNotification;
use App\Notifications\CheckinLicenseSeatNotification;
use App\Notifications\CheckoutAccessoryNotification;
use App\Notifications\CheckoutAssetNotification;
use App\Notifications\CheckoutComponentNotification;
use App\Notifications\CheckoutConsumableNotification;
use App\Notifications\CheckoutLicenseSeatNotification;
use GuzzleHttp\Exception\ClientException;
@@ -39,7 +43,7 @@ use Osama\LaravelTeamsNotification\TeamsNotification;
class CheckoutableListener
{
private array $skipNotificationsFor = [
Component::class,
// Component::class,
];
/**
@@ -145,7 +149,6 @@ class CheckoutableListener
$shouldSendEmailToUser = $this->checkoutableCategoryShouldSendEmail($event->checkoutable);
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress();
$shouldSendWebhookNotification = $this->shouldSendWebhookNotification();
if (!$shouldSendEmailToUser && !$shouldSendEmailToAlertAddress && !$shouldSendWebhookNotification) {
return;
}
@@ -269,6 +272,9 @@ class CheckoutableListener
case LicenseSeat::class:
$notificationClass = CheckinLicenseSeatNotification::class;
break;
case Component::class:
$notificationClass = CheckinComponentNotification::class;
break;
}
Log::debug('Notification class: '.$notificationClass);
@@ -299,6 +305,9 @@ class CheckoutableListener
case LicenseSeat::class:
$notificationClass = CheckoutLicenseSeatNotification::class;
break;
case Component::class:
$notificationClass = CheckoutComponentNotification::class;
break;
}
@@ -310,6 +319,7 @@ class CheckoutableListener
Asset::class => CheckoutAssetMail::class,
LicenseSeat::class => CheckoutLicenseMail::class,
Consumable::class => CheckoutConsumableMail::class,
Component::class => CheckoutComponentMail::class,
];
$mailable= $lookup[get_class($event->checkoutable)];
@@ -322,8 +332,8 @@ class CheckoutableListener
Accessory::class => CheckinAccessoryMail::class,
Asset::class => CheckinAssetMail::class,
LicenseSeat::class => CheckinLicenseMail::class,
Component::class => CheckinComponentMail::class,
];
$mailable= $lookup[get_class($event->checkoutable)];
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
@@ -469,7 +479,8 @@ class CheckoutableListener
return match (true) {
$checkoutable instanceof Asset => $checkoutable->model->category,
$checkoutable instanceof Accessory,
$checkoutable instanceof Consumable => $checkoutable->category,
$checkoutable instanceof Consumable,
$checkoutable instanceof Component => $checkoutable->category,
$checkoutable instanceof LicenseSeat => $checkoutable->license->category,
};
}

View File

@@ -0,0 +1,71 @@
<?php
namespace App\Mail;
use App\Models\Accessory;
use App\Models\Component;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class CheckinComponentMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(Component $component, $checkedOutTo, User $checkedInby, $note)
{
$this->item = $component;
$this->target = $checkedOutTo;
$this->admin = $checkedInby;
$this->note = $note;
$this->settings = Setting::getSettings();
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
$from = new Address(config('mail.from.address'), config('mail.from.name'));
return new Envelope(
from: $from,
subject: trans('mail.Confirm_component_checkin'),
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
markdown: 'mail.markdown.checkin-component',
with: [
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
]
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace App\Mail;
use App\Models\Component;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class CheckoutComponentMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(Component $component, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
{
$this->item = $component;
$this->admin = $checkedOutBy;
$this->note = $note;
$this->target = $checkedOutTo;
$this->acceptance = $acceptance;
$this->qty = $component->assets->first()?->pivot?->assigned_qty;
$this->settings = Setting::getSettings();
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
$from = new Address(config('mail.from.address'), config('mail.from.name'));
return new Envelope(
from: $from,
subject: trans('mail.Confirm_component_delivery'),
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
$eula = $this->item->getEula();
$req_accept = $this->item->requireAcceptance();
$accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
return new Content(
markdown: 'mail.markdown.checkout-component',
with: [
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
'eula' => $eula,
'req_accept' => $req_accept,
'accept_url' => $accept_url,
'qty' => $this->qty,
]
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@@ -15,7 +15,7 @@ use Watson\Validating\ValidatingTrait;
/**
* Model for Accessories.
*
* @version v1.0
* @version v1.0
*/
class Accessory extends SnipeModel
{
@@ -56,8 +56,8 @@ class Accessory extends SnipeModel
];
/**
* Accessory validation rules
*/
* Accessory validation rules
*/
public $rules = [
'name' => 'required|min:3|max:255',
'qty' => 'required|integer|min:1',
@@ -71,12 +71,12 @@ class Accessory extends SnipeModel
/**
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
* is not set in the model it will default to true.
*
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
* is not set in the model it will default to true.
*
* @var bool
*/
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
@@ -108,7 +108,7 @@ class Accessory extends SnipeModel
* Establishes the accessory -> supplier relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function supplier()
@@ -121,7 +121,7 @@ class Accessory extends SnipeModel
* Sets the requestable attribute on the accessory
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return void
*/
public function setRequestableAttribute($value)
@@ -136,7 +136,7 @@ class Accessory extends SnipeModel
* Establishes the accessory -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company()
@@ -148,7 +148,7 @@ class Accessory extends SnipeModel
* Establishes the accessory -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location()
@@ -160,7 +160,7 @@ class Accessory extends SnipeModel
* Establishes the accessory -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category()
@@ -172,7 +172,7 @@ class Accessory extends SnipeModel
* Returns the action logs associated with the accessory
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog()
@@ -201,8 +201,8 @@ class Accessory extends SnipeModel
*
* It's super-mega-assy, but it's the best I could do for now.
*
* @author A. Gianotto <snipe@snipe.net>
* @since v5.0.0
* @author A. Gianotto <snipe@snipe.net>
* @since v5.0.0
*
* @see \App\Http\Controllers\Api\AccessoriesController\checkedout()
*/
@@ -219,7 +219,7 @@ class Accessory extends SnipeModel
* presenter or service provider
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return string
*/
public function getImageUrl()
@@ -235,7 +235,7 @@ class Accessory extends SnipeModel
* Establishes the accessory -> users relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function checkouts()
@@ -248,7 +248,7 @@ class Accessory extends SnipeModel
* Establishes the accessory -> admin user relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v7.0.13]
* @since [v7.0.13]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
@@ -260,7 +260,7 @@ class Accessory extends SnipeModel
* Checks whether or not the accessory has users
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return int
*/
public function hasUsers()
@@ -274,7 +274,7 @@ class Accessory extends SnipeModel
* Establishes the accessory -> manufacturer relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer()
@@ -287,7 +287,7 @@ class Accessory extends SnipeModel
* accessory based on the category it belongs to.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return bool
*/
public function checkin_email()
@@ -300,7 +300,7 @@ class Accessory extends SnipeModel
* accept it via email.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return bool
*/
public function requireAcceptance()
@@ -313,7 +313,7 @@ class Accessory extends SnipeModel
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return string
*/
public function getEula()
@@ -333,7 +333,7 @@ class Accessory extends SnipeModel
* Check how many items within an accessory are checked out
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
* @since [v5.0]
* @return int
*/
public function numCheckedOut()
@@ -350,7 +350,7 @@ class Accessory extends SnipeModel
* bad things happen.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return int
*/
public function numRemaining()
@@ -365,8 +365,8 @@ class Accessory extends SnipeModel
/**
* Run after the checkout acceptance was declined by the user
*
* @param User $acceptedBy
* @param string $signature
* @param User $acceptedBy
* @param string $signature
*/
public function declinedCheckout(User $declinedBy, $signature)
{
@@ -392,8 +392,8 @@ class Accessory extends SnipeModel
* This simply checks that there is a value for quantity, and if there isn't, set it to 0.
*
* @author A. Gianotto <snipe@snipe.net>
* @since v6.3.4
* @param $value
* @since v6.3.4
* @param $value
* @return void
*/
public function setQtyAttribute($value)
@@ -410,7 +410,6 @@ class Accessory extends SnipeModel
/**
* Query builder scope to order on created_by name
*
*/
public function scopeOrderByCreatedByName($query, $order)
{
@@ -418,68 +417,68 @@ class Accessory extends SnipeModel
}
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderCompany($query, $order)
{
return $query->leftJoin('companies', 'accessories.company_id', '=', 'companies.id')
->orderBy('companies.name', $order);
->orderBy('companies.name', $order);
}
/**
* Query builder scope to order on category
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
* Query builder scope to order on category
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderCategory($query, $order)
{
return $query->leftJoin('categories', 'accessories.category_id', '=', 'categories.id')
->orderBy('categories.name', $order);
->orderBy('categories.name', $order);
}
/**
* Query builder scope to order on location
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
* Query builder scope to order on location
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderLocation($query, $order)
{
return $query->leftJoin('locations', 'accessories.location_id', '=', 'locations.id')
->orderBy('locations.name', $order);
->orderBy('locations.name', $order);
}
/**
* Query builder scope to order on manufacturer
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
* Query builder scope to order on manufacturer
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderManufacturer($query, $order)
{
return $query->leftJoin('manufacturers', 'accessories.manufacturer_id', '=', 'manufacturers.id')->orderBy('manufacturers.name', $order);
}
/**
* Query builder scope to order on supplier
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
* Query builder scope to order on supplier
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderSupplier($query, $order)
{
return $query->leftJoin('suppliers', 'accessories.supplier_id', '=', 'suppliers.id')->orderBy('suppliers.name', $order);

View File

@@ -16,7 +16,7 @@ use Watson\Validating\ValidatingTrait;
/**
* Model for Accessories.
*
* @version v1.0
* @version v1.0
*/
class AccessoryCheckout extends Model
{
@@ -36,7 +36,7 @@ class AccessoryCheckout extends Model
* Establishes the accessory checkout -> accessory relationship
*
* @author [A. Kroeger]
* @since [v7.0.9]
* @since [v7.0.9]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function accessory()
@@ -52,7 +52,7 @@ class AccessoryCheckout extends Model
* Establishes the accessory checkout -> user relationship
*
* @author [A. Kroeger]
* @since [v7.0.9]
* @since [v7.0.9]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
@@ -64,7 +64,7 @@ class AccessoryCheckout extends Model
* Get the target this asset is checked out to
*
* @author [A. Kroeger]
* @since [v7.0]
* @since [v7.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assignedTo()
@@ -76,7 +76,7 @@ class AccessoryCheckout extends Model
* Gets the lowercased name of the type of target the asset is assigned to
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return string
*/
public function assignedType()
@@ -91,7 +91,7 @@ class AccessoryCheckout extends Model
* this method is an easy way of seeing if we are checked out to a user.
*
* @author [A. Kroeger]
* @since [v7.0]
* @since [v7.0]
*/
public function checkedOutToUser(): bool
{
@@ -127,50 +127,64 @@ class AccessoryCheckout extends Model
* Run additional, advanced searches.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $terms The search terms
* @param array $terms The search terms
* @return \Illuminate\Database\Eloquent\Builder
*/
public function advancedTextSearch(Builder $query, array $terms)
{
$userQuery = User::where(function ($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('first_name', 'like', $search_str)
->orWhere('last_name', 'like', $search_str)
->orWhere('note', 'like', $search_str);
$userQuery = User::where(
function ($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('first_name', 'like', $search_str)
->orWhere('last_name', 'like', $search_str)
->orWhere('note', 'like', $search_str);
}
}
})->select('id');
)->select('id');
$locationQuery = Location::where(function ($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('name', 'like', $search_str);
$locationQuery = Location::where(
function ($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('name', 'like', $search_str);
}
}
})->select('id');
)->select('id');
$assetQuery = Asset::where(function ($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('name', 'like', $search_str);
$assetQuery = Asset::where(
function ($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('name', 'like', $search_str);
}
}
})->select('id');
)->select('id');
$query->where(function ($query) use ($userQuery) {
$query->where('assigned_type', User::class)
->whereIn('assigned_to', $userQuery);
})->orWhere(function($query) use ($locationQuery) {
$query->where('assigned_type', Location::class)
->whereIn('assigned_to', $locationQuery);
})->orWhere(function($query) use ($assetQuery) {
$query->where('assigned_type', Asset::class)
->whereIn('assigned_to', $assetQuery);
})->orWhere(function($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('note', 'like', $search_str);
$query->where(
function ($query) use ($userQuery) {
$query->where('assigned_type', User::class)
->whereIn('assigned_to', $userQuery);
}
});
)->orWhere(
function ($query) use ($locationQuery) {
$query->where('assigned_type', Location::class)
->whereIn('assigned_to', $locationQuery);
}
)->orWhere(
function ($query) use ($assetQuery) {
$query->where('assigned_type', Asset::class)
->whereIn('assigned_to', $assetQuery);
}
)->orWhere(
function ($query) use ($terms) {
foreach ($terms as $term) {
$search_str = '%' . $term . '%';
$query->where('note', 'like', $search_str);
}
}
);
return $query;
}

View File

@@ -12,7 +12,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* Model for the Actionlog (the table that keeps a historical log of
* checkouts, checkins, and updates).
*
* @version v1.0
* @version v1.0
*/
class Actionlog extends SnipeModel
{
@@ -74,6 +74,8 @@ class Actionlog extends SnipeModel
'assets' => ['asset_tag','name', 'serial', 'order_number', 'notes', 'purchase_date'],
'assets.model' => ['name', 'model_number', 'eol', 'notes'],
'assets.model.category' => ['name', 'notes'],
'assets.location' => ['name'],
'assets.defaultLoc' => ['name'],
'assets.model.manufacturer' => ['name', 'notes'],
'licenses' => ['name', 'serial', 'notes', 'order_number', 'license_email', 'license_name', 'purchase_order', 'purchase_date'],
'licenses.category' => ['name', 'notes'],
@@ -96,29 +98,31 @@ class Actionlog extends SnipeModel
* Override from Builder to automatically add the company
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public static function boot()
{
parent::boot();
static::creating(function (self $actionlog) {
// If the admin is a superadmin, let's see if the target instead has a company.
if (auth()->user() && auth()->user()->isSuperUser()) {
if ($actionlog->target) {
$actionlog->company_id = $actionlog->target->company_id;
} elseif ($actionlog->item) {
$actionlog->company_id = $actionlog->item->company_id;
static::creating(
function (self $actionlog) {
// If the admin is a superadmin, let's see if the target instead has a company.
if (auth()->user() && auth()->user()->isSuperUser()) {
if ($actionlog->target) {
$actionlog->company_id = $actionlog->target->company_id;
} elseif ($actionlog->item) {
$actionlog->company_id = $actionlog->item->company_id;
}
} elseif (auth()->user() && auth()->user()->company) {
$actionlog->company_id = auth()->user()->company_id;
}
} elseif (auth()->user() && auth()->user()->company) {
$actionlog->company_id = auth()->user()->company_id;
}
if ($actionlog->action_date == '') {
$actionlog->action_date = Carbon::now();
}
if ($actionlog->action_date == '') {
$actionlog->action_date = Carbon::now();
}
});
}
);
}
@@ -126,7 +130,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> item relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function item()
@@ -138,7 +142,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company()
@@ -151,7 +155,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> asset relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets()
@@ -163,7 +167,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> license relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenses()
@@ -175,7 +179,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> consumable relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function consumables()
@@ -187,7 +191,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> consumable relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function accessories()
@@ -199,7 +203,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> components relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function components()
@@ -211,7 +215,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> item type relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function itemType()
@@ -227,7 +231,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> target type relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function targetType()
@@ -244,7 +248,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> uploads relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads()
@@ -258,7 +262,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> userlog relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function userlog()
@@ -270,7 +274,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> admin user relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
@@ -283,7 +287,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> user relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function user()
@@ -296,7 +300,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> target relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function target()
@@ -308,7 +312,7 @@ class Actionlog extends SnipeModel
* Establishes the actionlog -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location()
@@ -321,7 +325,7 @@ class Actionlog extends SnipeModel
* Check if the file exists, and if it does, force a download
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return string | false
*/
public function get_src($type = 'assets', $fieldname = 'filename')
@@ -339,7 +343,7 @@ class Actionlog extends SnipeModel
* Saves the log record with the action type
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return bool
*/
public function logaction($actiontype)
@@ -360,7 +364,7 @@ class Actionlog extends SnipeModel
* Calculate the number of days until the next audit
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return int
*/
public function daysUntilNextAudit($monthInterval = 12, $asset = null)
@@ -389,7 +393,7 @@ class Actionlog extends SnipeModel
* Calculate the date of the next audit
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return \Datetime
*/
public function calcNextAuditDate($monthInterval = 12, $asset = null)
@@ -406,8 +410,8 @@ class Actionlog extends SnipeModel
/**
* Gets action logs in chronological order, excluding uploads
*
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @since v1.0
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @since v1.0
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getListingOfActionLogsChronologicalOrder()
@@ -423,7 +427,7 @@ class Actionlog extends SnipeModel
* Determines what the type of request is so we can log it to the action_log
*
* @author A. Gianotto <snipe@snipe.net>
* @since v6.3.0
* @since v6.3.0
* @return string
*/
public function determineActionSource(): string
@@ -435,7 +439,8 @@ class Actionlog extends SnipeModel
// This is an API call
if (((request()->header('content-type') && (request()->header('accept'))=='application/json'))
&& (starts_with(request()->header('authorization'), 'Bearer '))) {
&& (starts_with(request()->header('authorization'), 'Bearer '))
) {
return 'api';
}
@@ -453,24 +458,24 @@ class Actionlog extends SnipeModel
{
switch ($this->item_type) {
case Accessory::class:
return route('show.accessoryfile', [$this->item_id, $this->id]);
case Asset::class:
return route('show/assetfile', [$this->item_id, $this->id]);
case AssetModel::class:
return route('show/modelfile', [$this->item_id, $this->id]);
case Consumable::class:
return route('show/locationsfile', [$this->item_id, $this->id]);
case Component::class:
return route('show.componentfile', [$this->item_id, $this->id]);
case License::class:
return route('show.licensefile', [$this->item_id, $this->id]);
case Location::class:
return route('show/locationsfile', [$this->item_id, $this->id]);
case User::class:
return route('show/userfile', [$this->item_id, $this->id]);
default:
return null;
case Accessory::class:
return route('show.accessoryfile', [$this->item_id, $this->id]);
case Asset::class:
return route('show/assetfile', [$this->item_id, $this->id]);
case AssetModel::class:
return route('show/modelfile', [$this->item_id, $this->id]);
case Consumable::class:
return route('show/locationsfile', [$this->item_id, $this->id]);
case Component::class:
return route('show.componentfile', [$this->item_id, $this->id]);
case License::class:
return route('show.licensefile', [$this->item_id, $this->id]);
case Location::class:
return route('show/locationsfile', [$this->item_id, $this->id]);
case User::class:
return route('show/userfile', [$this->item_id, $this->id]);
default:
return null;
}
}
@@ -478,24 +483,24 @@ class Actionlog extends SnipeModel
{
switch ($this->item_type) {
case Accessory::class:
return 'private_uploads/accessories/'.$this->filename;
case Asset::class:
return 'private_uploads/assets/'.$this->filename;
case AssetModel::class:
return 'private_uploads/assetmodels/'.$this->filename;
case Consumable::class:
return 'private_uploads/consumables/'.$this->filename;
case Component::class:
return 'private_uploads/components/'.$this->filename;
case License::class:
return 'private_uploads/licenses/'.$this->filename;
case Location::class:
return 'private_uploads/locations/'.$this->filename;
case User::class:
return 'private_uploads/users/'.$this->filename;
default:
return null;
case Accessory::class:
return 'private_uploads/accessories/'.$this->filename;
case Asset::class:
return 'private_uploads/assets/'.$this->filename;
case AssetModel::class:
return 'private_uploads/assetmodels/'.$this->filename;
case Consumable::class:
return 'private_uploads/consumables/'.$this->filename;
case Component::class:
return 'private_uploads/components/'.$this->filename;
case License::class:
return 'private_uploads/licenses/'.$this->filename;
case Location::class:
return 'private_uploads/locations/'.$this->filename;
case User::class:
return 'private_uploads/users/'.$this->filename;
default:
return null;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ use Watson\Validating\ValidatingTrait;
/**
* Model for Asset Maintenances.
*
* @version v1.0
* @version v1.0
*/
class AssetMaintenance extends Model implements ICompanyableChild
{
@@ -93,7 +93,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
/**
* getImprovementOptions
*
* @return array
* @return array
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
@@ -157,21 +157,21 @@ class AssetMaintenance extends Model implements ICompanyableChild
* asset
* Get asset for this improvement
*
* @return mixed
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function asset()
{
return $this->belongsTo(\App\Models\Asset::class, 'asset_id')
->withTrashed();
->withTrashed();
}
/**
* Get the admin who created the maintenance
*
* @return mixed
* @return mixed
* @author A. Gianotto <snipe@snipe.net>
* @version v3.0
*/
@@ -184,7 +184,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
public function supplier()
{
return $this->belongsTo(\App\Models\Supplier::class, 'supplier_id')
->withTrashed();
->withTrashed();
}
/**
@@ -196,8 +196,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
/**
* Query builder scope to order on a supplier
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -212,8 +212,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
/**
* Query builder scope to order on asset tag
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -226,8 +226,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
/**
* Query builder scope to order on asset tag
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -240,8 +240,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
/**
* Query builder scope to order on serial
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -254,8 +254,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
/**
* Query builder scope to order on status label name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -269,8 +269,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
/**
* Query builder scope to order on status label name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/

View File

@@ -17,7 +17,7 @@ use App\Http\Traits\TwoColumnUniqueUndeletedTrait;
* Model for Asset Models. Asset Models contain higher level
* attributes that are common among the same type of asset.
*
* @version v1.0
* @version v1.0
*/
class AssetModel extends SnipeModel
{
@@ -105,7 +105,7 @@ class AssetModel extends SnipeModel
* Establishes the model -> assets relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets()
@@ -117,7 +117,7 @@ class AssetModel extends SnipeModel
* Establishes the model -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category()
@@ -129,7 +129,7 @@ class AssetModel extends SnipeModel
* Establishes the model -> depreciation relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function depreciation()
@@ -141,7 +141,7 @@ class AssetModel extends SnipeModel
* Establishes the model -> manufacturer relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer()
@@ -153,7 +153,7 @@ class AssetModel extends SnipeModel
* Establishes the model -> fieldset relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function fieldset()
@@ -163,14 +163,14 @@ class AssetModel extends SnipeModel
public function customFields()
{
return $this->fieldset()->first()->fields();
return $this->fieldset()->first()->fields();
}
/**
* Establishes the model -> custom field default values relationship
*
* @author hannah tinkler
* @since [v4.3]
* @since [v4.3]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function defaultValues()
@@ -184,7 +184,7 @@ class AssetModel extends SnipeModel
* @todo this should probably be moved
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function getImageUrl()
@@ -201,7 +201,7 @@ class AssetModel extends SnipeModel
* Checks if the model is deletable
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v6.3.4]
* @since [v6.3.4]
* @return bool
*/
public function isDeletable()
@@ -216,7 +216,7 @@ class AssetModel extends SnipeModel
* Get user who created the item
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
@@ -235,10 +235,10 @@ class AssetModel extends SnipeModel
* scopeInCategory
* Get all models that are in the array of category ids
*
* @param $query
* @param $query
* @param array $categoryIdListing
*
* @return mixed
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
@@ -251,9 +251,9 @@ class AssetModel extends SnipeModel
* scopeRequestable
* Get all models that are requestable by a user.
*
* @param $query
* @param $query
*
* @return $query
* @return $query
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
* @version v3.5
*/
@@ -265,8 +265,8 @@ class AssetModel extends SnipeModel
/**
* Query builder scope to search on text, including catgeory and manufacturer name
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $search Search term
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $search Search term
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
@@ -274,23 +274,31 @@ class AssetModel extends SnipeModel
{
return $query->where('models.name', 'LIKE', "%$search%")
->orWhere('model_number', 'LIKE', "%$search%")
->orWhere(function ($query) use ($search) {
$query->whereHas('category', function ($query) use ($search) {
$query->where('categories.name', 'LIKE', '%'.$search.'%');
});
})
->orWhere(function ($query) use ($search) {
$query->whereHas('manufacturer', function ($query) use ($search) {
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
});
});
->orWhere(
function ($query) use ($search) {
$query->whereHas(
'category', function ($query) use ($search) {
$query->where('categories.name', 'LIKE', '%'.$search.'%');
}
);
}
)
->orWhere(
function ($query) use ($search) {
$query->whereHas(
'manufacturer', function ($query) use ($search) {
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
}
);
}
);
}
/**
* Query builder scope to order on manufacturer
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -302,8 +310,8 @@ class AssetModel extends SnipeModel
/**
* Query builder scope to order on category name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -319,7 +327,6 @@ class AssetModel extends SnipeModel
/**
* Query builder scope to order on created_by name
*
*/
public function scopeOrderByCreatedByName($query, $order)
{

View File

@@ -18,7 +18,7 @@ use Illuminate\Support\Str;
* to require acceptance from the user, whether or not to
* send a EULA to the user, etc.
*
* @version v1.0
* @version v1.0
*/
class Category extends SnipeModel
{
@@ -96,7 +96,7 @@ class Category extends SnipeModel
* Checks if category can be deleted
*
* @author [Dan Meltzer] [<dmeltzer.devel@gmail.com>]
* @since [v5.0]
* @since [v5.0]
* @return bool
*/
public function isDeletable()
@@ -119,7 +119,7 @@ class Category extends SnipeModel
* Establishes the category -> accessories relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function accessories()
@@ -131,7 +131,7 @@ class Category extends SnipeModel
* Establishes the category -> licenses relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.3]
* @since [v4.3]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenses()
@@ -143,7 +143,7 @@ class Category extends SnipeModel
* Establishes the category -> consumables relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function consumables()
@@ -155,7 +155,7 @@ class Category extends SnipeModel
* Establishes the category -> consumables relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function components()
@@ -170,7 +170,7 @@ class Category extends SnipeModel
* It should only be used in a single category context.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @since [v2.0]
* @return int
*/
public function itemCount()
@@ -181,18 +181,18 @@ class Category extends SnipeModel
}
switch ($this->category_type) {
case 'asset':
return $this->assets->count();
case 'accessory':
return $this->accessories->count();
case 'component':
return $this->components->count();
case 'consumable':
return $this->consumables->count();
case 'license':
return $this->licenses->count();
default:
return 0;
case 'asset':
return $this->assets->count();
case 'accessory':
return $this->accessories->count();
case 'component':
return $this->components->count();
case 'consumable':
return $this->consumables->count();
case 'license':
return $this->licenses->count();
default:
return 0;
}
}
@@ -201,7 +201,7 @@ class Category extends SnipeModel
* Establishes the category -> assets relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets()
@@ -218,8 +218,8 @@ class Category extends SnipeModel
* by their category.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.1.0]
* @see \App\Models\Asset::scopeAssetsForShow()
* @since [v6.1.0]
* @see \App\Models\Asset::scopeAssetsForShow()
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function showableAssets()
@@ -231,7 +231,7 @@ class Category extends SnipeModel
* Establishes the category -> models relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function models()
@@ -249,7 +249,7 @@ class Category extends SnipeModel
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @since [v2.0]
* @return string | null
*/
public function getEula()
@@ -276,7 +276,7 @@ class Category extends SnipeModel
*
* This will also correctly parse a 1/0 if "true"/"false" is passed.
*
* @param $value
* @param $value
* @return void
*/
public function setCheckinEmailAttribute($value)
@@ -293,9 +293,9 @@ class Category extends SnipeModel
/**
* Query builder scope for whether or not the category requires acceptance
*
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @author Vincent Sposato <vincent.sposato@gmail.com>
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeRequiresAcceptance($query)

View File

@@ -66,7 +66,7 @@ class CheckoutAcceptance extends Model
/**
* Was the checkoutable checked out to this user?
*
* @param User $user
* @param User $user
* @return bool
*/
public function isCheckedOutTo(User $user)
@@ -79,7 +79,7 @@ class CheckoutAcceptance extends Model
* Do not add stuff here that doesn't have a corresponding column in the
* checkout_acceptances table or you'll get an error.
*
* @param string $signature_filename
* @param string $signature_filename
*/
public function accept($signature_filename, $eula = null, $filename = null, $note = null)
{
@@ -99,7 +99,7 @@ class CheckoutAcceptance extends Model
/**
* Decline the checkout acceptance
*
* @param string $signature_filename
* @param string $signature_filename
*/
public function decline($signature_filename, $note = null)
{
@@ -116,8 +116,9 @@ class CheckoutAcceptance extends Model
/**
* Filter checkout acceptences by the user
*
* @param Illuminate\Database\Eloquent\Builder $query
* @param User $user
* @param User $user
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeForUser(Builder $query, User $user)
@@ -127,6 +128,7 @@ class CheckoutAcceptance extends Model
/**
* Filter to only get pending acceptances
*
* @param Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/

View File

@@ -13,11 +13,13 @@ use Illuminate\Support\Facades\Schema;
/**
* Model for Companies.
*
* @version v1.8
* @version v1.8
*/
final class Company extends SnipeModel
{
use HasFactory;
use CompanyableTrait;
protected $table = 'companies';
@@ -26,19 +28,19 @@ final class Company extends SnipeModel
'name' => 'required|min:1|max:255|unique:companies,name',
'fax' => 'min:7|max:35|nullable',
'phone' => 'min:7|max:35|nullable',
'email' => 'email|max:150|nullable',
'email' => 'email|max:150|nullable',
];
protected $presenter = \App\Presenters\CompanyPresenter::class;
use Presentable;
/**
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
* is not set in the model it will default to true.
*
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
* is not set in the model it will default to true.
*
* @var bool
*/
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
use Searchable;
@@ -100,7 +102,7 @@ final class Company extends SnipeModel
* account the full multiple company support setting
* and if the current user is a super user.
*
* @param $unescaped_input
* @param $unescaped_input
* @return int|mixed|string|null
*/
public static function getIdForCurrentUser($unescaped_input)
@@ -127,7 +129,7 @@ final class Company extends SnipeModel
* Check to see if the current user should have access to the model.
* I hate this method and I think it should be refactored.
*
* @param $companyable
* @param $companyable
* @return bool|void
*/
public static function isCurrentUserHasAccess($companyable)
@@ -146,10 +148,10 @@ final class Company extends SnipeModel
if (!is_string($companyable)) {
$company_table = $companyable->getModel()->getTable();
try {
// This is primary for the gate:allows-check in location->isDeletable()
// This is primarily for the gate:allows-check in location->isDeletable()
// Locations don't have a company_id so without this it isn't possible to delete locations with FullMultipleCompanySupport enabled
// because this function is called by SnipePermissionsPolicy->before()
if (!$companyable instanceof Company && !Schema::hasColumn($company_table, 'company_id')) {
if (!Schema::hasColumn($company_table, 'company_id')) {
return true;
}
@@ -163,9 +165,16 @@ final class Company extends SnipeModel
// Log::warning('Companyable is '.$companyable);
$current_user_company_id = auth()->user()->company_id;
$companyable_company_id = $companyable->company_id;
return $current_user_company_id == null || $current_user_company_id == $companyable_company_id || auth()->user()->isSuperUser();
// Set this to check companyable on company
if ($companyable instanceof Company) {
$companyable_company_id = $companyable->id;
}
return ($current_user_company_id == null) || ($current_user_company_id == $companyable_company_id) || auth()->user()->isSuperUser();
}
return false;
}
public static function isCurrentUserAuthorized()
@@ -183,7 +192,7 @@ final class Company extends SnipeModel
* Checks if company can be deleted
*
* @author [Dan Meltzer] [<dmeltzer.devel@gmail.com>]
* @since [v5.0]
* @since [v5.0]
* @return bool
*/
public function isDeletable()
@@ -200,7 +209,7 @@ final class Company extends SnipeModel
}
/**
* @param $unescaped_input
* @param $unescaped_input
* @return int|mixed|string|null
*/
public static function getIdForUser($unescaped_input)
@@ -256,14 +265,14 @@ final class Company extends SnipeModel
* @todo - refactor that trait to handle the user's model as well.
*
* @author [A. Gianotto] <snipe@snipe.net>
* @param $query
* @param $column
* @param $table_name
* @param $query
* @param $column
* @param $table_name
* @return mixed
*/
public static function scopeCompanyables($query, $column = 'company_id', $table_name = null)
{
// If not logged in and hitting this, assume we are on the command line and don't scope?'
// If not logged in and hitting this, assume we are on the command line and don't scope?
if (! static::isFullMultipleCompanySupportEnabled() || (Auth::hasUser() && auth()->user()->isSuperUser()) || (! Auth::hasUser())) {
return $query;
} else {
@@ -280,11 +289,16 @@ final class Company extends SnipeModel
private static function scopeCompanyablesDirectly($query, $column = 'company_id', $table_name = null)
{
$company_id = null;
// Get the company ID of the logged-in user, or set it to null if there is no company associated with the user
if (Auth::hasUser()) {
$company_id = auth()->user()->company_id;
} else {
$company_id = null;
}
// If we are scoping the companies table itself, look for the company.id
if ($query->getModel()->getTable() == 'companies') {
return $query->where('companies.id', '=', $company_id);
}
@@ -297,6 +311,8 @@ final class Company extends SnipeModel
return $query->where($table.$column, '=', $company_id);
}
}
public function adminuser()
@@ -311,8 +327,8 @@ final class Company extends SnipeModel
* This gets invoked by CompanyableChildScope, but I'm not sure what it does.
*
* @author [A. Gianotto] <snipe@snipe.net>
* @param array $companyable_names
* @param $query
* @param array $companyable_names
* @param $query
* @return mixed
*/
public static function scopeCompanyableChildren(array $companyable_names, $query)
@@ -324,17 +340,18 @@ final class Company extends SnipeModel
return $query;
} else {
$f = function ($q) {
Log::debug('scopeCompanyablesDirectly firing ');
static::scopeCompanyablesDirectly($q);
};
$q = $query->where(function ($q) use ($companyable_names, $f) {
$q2 = $q->whereHas($companyable_names[0], $f);
$q = $query->where(
function ($q) use ($companyable_names, $f) {
$q2 = $q->whereHas($companyable_names[0], $f);
for ($i = 1; $i < count($companyable_names); $i++) {
$q2 = $q2->orWhereHas($companyable_names[$i], $f);
for ($i = 1; $i < count($companyable_names); $i++) {
$q2 = $q2->orWhereHas($companyable_names[$i], $f);
}
}
});
);
return $q;
}

View File

@@ -9,15 +9,15 @@ use Illuminate\Database\Eloquent\Scope;
/**
* Handle query scoping for full company support.
*
* @todo Move this to a more Laravel 5.2 esque way
* @version v1.0
* @todo Move this to a more Laravel 5.2 esque way
* @version v1.0
*/
final class CompanyableChildScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
public function apply(Builder $builder, Model $model)
@@ -31,7 +31,7 @@ final class CompanyableChildScope implements Scope
* @todo IMPLEMENT
* Remove the scope from the given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
public function remove(Builder $builder)

View File

@@ -9,15 +9,15 @@ use Illuminate\Database\Eloquent\Scope;
/**
* Handle query scoping for full company support.
*
* @todo Move this to a more Laravel 5.2 esque way
* @version v1.0
* @todo Move this to a more Laravel 5.2 esque way
* @version v1.0
*/
final class CompanyableScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
public function apply(Builder $builder, Model $model)
@@ -29,7 +29,7 @@ final class CompanyableScope implements Scope
* @todo IMPLEMENT
* Remove the scope from the given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
public function remove(Builder $builder)

View File

@@ -8,7 +8,7 @@ trait CompanyableTrait
* This trait is used to scope models to the current company. To use this scope on companyable models,
* we use the "use Companyable;" statement at the top of the mode.
*
* @see \App\Models\Company\Company::scopeCompanyables()
* @see \App\Models\Company\Company::scopeCompanyables()
* @return void
*/
public static function bootCompanyableTrait()

View File

@@ -2,18 +2,20 @@
namespace App\Models;
use App\Helpers\Helper;
use App\Models\Traits\HasUploads;
use App\Models\Traits\Searchable;
use App\Presenters\Presentable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Storage;
use Watson\Validating\ValidatingTrait;
/**
* Model for Components.
*
* @version v1.0
* @version v1.0
*/
class Component extends SnipeModel
{
@@ -121,7 +123,7 @@ class Component extends SnipeModel
* Establishes the component -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location()
@@ -133,7 +135,7 @@ class Component extends SnipeModel
* Establishes the component -> assets relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets()
@@ -147,7 +149,7 @@ class Component extends SnipeModel
* @todo this is probably not needed - refactor
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
@@ -159,7 +161,7 @@ class Component extends SnipeModel
* Establishes the component -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company()
@@ -171,7 +173,7 @@ class Component extends SnipeModel
* Establishes the component -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category()
@@ -183,7 +185,7 @@ class Component extends SnipeModel
* Establishes the item -> supplier relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.1.1]
* @since [v6.1.1]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function supplier()
@@ -196,19 +198,49 @@ class Component extends SnipeModel
* Establishes the item -> manufacturer relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer()
{
return $this->belongsTo(\App\Models\Manufacturer::class, 'manufacturer_id');
}
/**
* Determine whether this asset requires acceptance by the assigned user
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return bool
*/
public function requireAcceptance()
{
return $this->category->require_acceptance;
}
/**
* Checks for a category-specific EULA, and if that doesn't exist,
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return string | false
*/
public function getEula()
{
if ($this->category->eula_text) {
return Helper::parseEscapedMarkedown($this->category->eula_text);
} elseif ((Setting::getSettings()->default_eula_text) && ($this->category->use_default_eula == '1')) {
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
} else {
return null;
}
}
/**
* Establishes the component -> action logs relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog()
@@ -220,7 +252,7 @@ class Component extends SnipeModel
* Check how many items within a component are checked out
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
* @since [v5.0]
* @return int
*/
public function numCheckedOut()
@@ -239,20 +271,34 @@ class Component extends SnipeModel
*
* This allows us to get the assets with assigned components without the company restriction
*/
public function uncontrainedAssets() {
public function uncontrainedAssets()
{
return $this->belongsToMany(\App\Models\Asset::class, 'components_assets')
->withPivot('id', 'assigned_qty', 'created_at', 'created_by', 'note')
->withoutGlobalScope(new CompanyableScope);
->withPivot('id', 'assigned_qty', 'created_at', 'created_by', 'note')
->withoutGlobalScope(new CompanyableScope);
}
/**
* Determine whether to send a checkin/checkout email based on
* asset model category
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return bool
*/
public function checkin_email()
{
return $this->category?->checkin_email;
}
/**
* Check how many items within a component are remaining
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return int
*/
public function numRemaining()
@@ -275,8 +321,8 @@ class Component extends SnipeModel
* This simply checks that there is a value for quantity, and if there isn't, set it to 0.
*
* @author A. Gianotto <snipe@snipe.net>
* @since v6.3.4
* @param $value
* @since v6.3.4
* @param $value
* @return void
*/
public function setQtyAttribute($value)
@@ -294,8 +340,8 @@ class Component extends SnipeModel
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -307,8 +353,8 @@ class Component extends SnipeModel
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -320,8 +366,8 @@ class Component extends SnipeModel
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -333,8 +379,8 @@ class Component extends SnipeModel
/**
* Query builder scope to order on supplier
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -346,8 +392,8 @@ class Component extends SnipeModel
/**
* Query builder scope to order on manufacturer
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/

View File

@@ -125,7 +125,7 @@ class Consumable extends SnipeModel
* @todo Update this comment once it's been implemented
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function setRequestableAttribute($value)
@@ -140,7 +140,7 @@ class Consumable extends SnipeModel
* Establishes the consumable -> admin user relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
@@ -152,7 +152,7 @@ class Consumable extends SnipeModel
* Establishes the component -> assignments relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function consumableAssignments()
@@ -164,7 +164,7 @@ class Consumable extends SnipeModel
* Establishes the component -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company()
@@ -176,7 +176,7 @@ class Consumable extends SnipeModel
* Establishes the component -> manufacturer relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer()
@@ -188,7 +188,7 @@ class Consumable extends SnipeModel
* Establishes the component -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location()
@@ -200,7 +200,7 @@ class Consumable extends SnipeModel
* Establishes the component -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category()
@@ -213,7 +213,7 @@ class Consumable extends SnipeModel
* Establishes the component -> action logs relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog()
@@ -225,7 +225,7 @@ class Consumable extends SnipeModel
* Gets the full image url for the consumable
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return string | false
*/
public function getImageUrl()
@@ -241,7 +241,7 @@ class Consumable extends SnipeModel
* Establishes the component -> users relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
*/
public function users() : Relation
{
@@ -252,7 +252,7 @@ class Consumable extends SnipeModel
* Establishes the item -> supplier relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.1.1]
* @since [v6.1.1]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function supplier()
@@ -266,7 +266,7 @@ class Consumable extends SnipeModel
* asset model category
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return bool
*/
public function checkin_email()
@@ -278,7 +278,7 @@ class Consumable extends SnipeModel
* Determine whether this asset requires acceptance by the assigned user
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return bool
*/
public function requireAcceptance()
@@ -291,7 +291,7 @@ class Consumable extends SnipeModel
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return string | false
*/
public function getEula()
@@ -309,7 +309,7 @@ class Consumable extends SnipeModel
* Check how many items within a consumable are checked out
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
* @since [v5.0]
* @return int
*/
public function numCheckedOut()
@@ -321,7 +321,7 @@ class Consumable extends SnipeModel
* Checks the number of available consumables
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @since [v4.0]
* @return int
*/
public function numRemaining()
@@ -347,8 +347,8 @@ class Consumable extends SnipeModel
* This simply checks that there is a value for quantity, and if there isn't, set it to 0.
*
* @author A. Gianotto <snipe@snipe.net>
* @since v6.3.4
* @param $value
* @since v6.3.4
* @param $value
* @return void
*/
public function setQtyAttribute($value)
@@ -365,8 +365,8 @@ class Consumable extends SnipeModel
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -378,8 +378,8 @@ class Consumable extends SnipeModel
/**
* Query builder scope to order on location
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -391,8 +391,8 @@ class Consumable extends SnipeModel
/**
* Query builder scope to order on manufacturer
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -404,8 +404,8 @@ class Consumable extends SnipeModel
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -417,8 +417,8 @@ class Consumable extends SnipeModel
/**
* Query builder scope to order on remaining
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -431,8 +431,8 @@ class Consumable extends SnipeModel
/**
* Query builder scope to order on supplier
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/

View File

@@ -92,7 +92,7 @@ class CustomField extends Model
* table instead of the assets table.
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
* @since [v3.0]
*/
public static $table_name = 'assets';
@@ -103,7 +103,7 @@ class CustomField extends Model
* do with previously existing values. - @snipe
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @since [v3.4]
* @return string
*/
public static function name_to_db_name($name)
@@ -120,66 +120,78 @@ class CustomField extends Model
* to do it in the controllers.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @since [v3.4]
* @return bool
*/
public static function boot()
{
parent::boot();
self::created(function ($custom_field) {
self::created(
function ($custom_field) {
// Column already exists on the assets table - nothing to do here.
// This *shouldn't* happen in the wild.
if (Schema::hasColumn(self::$table_name, $custom_field->db_column)) {
return false;
// Column already exists on the assets table - nothing to do here.
// This *shouldn't* happen in the wild.
if (Schema::hasColumn(self::$table_name, $custom_field->db_column)) {
return false;
}
// Update the column name in the assets table
Schema::table(
self::$table_name, function ($table) use ($custom_field) {
$table->text($custom_field->convertUnicodeDbSlug())->nullable();
}
);
// Update the db_column property in the custom fields table
$custom_field->db_column = $custom_field->convertUnicodeDbSlug();
$custom_field->save();
}
);
// Update the column name in the assets table
Schema::table(self::$table_name, function ($table) use ($custom_field) {
$table->text($custom_field->convertUnicodeDbSlug())->nullable();
});
self::updating(
function ($custom_field) {
// Update the db_column property in the custom fields table
$custom_field->db_column = $custom_field->convertUnicodeDbSlug();
$custom_field->save();
});
// Column already exists on the assets table - nothing to do here.
if ($custom_field->isDirty('name')) {
if (Schema::hasColumn(self::$table_name, $custom_field->convertUnicodeDbSlug())) {
return true;
}
self::updating(function ($custom_field) {
// Rename the field if the name has changed
Schema::table(
self::$table_name, function ($table) use ($custom_field) {
$table->renameColumn($custom_field->convertUnicodeDbSlug($custom_field->getOriginal('name')), $custom_field->convertUnicodeDbSlug());
}
);
// Save the updated column name to the custom fields table
$custom_field->db_column = $custom_field->convertUnicodeDbSlug();
$custom_field->save();
// Column already exists on the assets table - nothing to do here.
if ($custom_field->isDirty('name')) {
if (Schema::hasColumn(self::$table_name, $custom_field->convertUnicodeDbSlug())) {
return true;
}
// Rename the field if the name has changed
Schema::table(self::$table_name, function ($table) use ($custom_field) {
$table->renameColumn($custom_field->convertUnicodeDbSlug($custom_field->getOriginal('name')), $custom_field->convertUnicodeDbSlug());
});
// Save the updated column name to the custom fields table
$custom_field->db_column = $custom_field->convertUnicodeDbSlug();
$custom_field->save();
return true;
}
return true;
});
);
// Drop the assets column if we've deleted it from custom fields
self::deleting(function ($custom_field) {
return Schema::table(self::$table_name, function ($table) use ($custom_field) {
$table->dropColumn($custom_field->db_column);
});
});
self::deleting(
function ($custom_field) {
return Schema::table(
self::$table_name, function ($table) use ($custom_field) {
$table->dropColumn($custom_field->db_column);
}
);
}
);
}
/**
* Establishes the customfield -> fieldset relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function fieldset()
@@ -214,26 +226,26 @@ class CustomField extends Model
public function displayFieldInCurrentForm($form_type = null)
{
switch ($form_type) {
case 'audit':
return $this->displayFieldInAuditForm();
case 'checkin':
return $this->displayFieldInCheckinForm();
case 'checkout':
return $this->displayFieldInCheckoutForm();
case 'audit':
return $this->displayFieldInAuditForm();
case 'checkin':
return $this->displayFieldInCheckinForm();
case 'checkout':
return $this->displayFieldInCheckoutForm();
}
}
public function assetModels()
{
return $this->fieldset()->with('models')->get()->pluck('models')->flatten()->unique('id');
return $this->fieldset()->with('models')->get()->pluck('models')->flatten()->unique('id');
}
/**
* Establishes the customfield -> admin user relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function user()
@@ -245,7 +257,7 @@ class CustomField extends Model
* Establishes the customfield -> default values relationship
*
* @author Hannah Tinkler
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function defaultValues()
@@ -262,19 +274,23 @@ class CustomField extends Model
*/
public function defaultValue($modelId)
{
return $this->defaultValues->filter(function ($item) use ($modelId) {
return $item->pivot->asset_model_id == $modelId;
})->map(function ($item) {
return $item->pivot->default_value;
})->first();
return $this->defaultValues->filter(
function ($item) use ($modelId) {
return $item->pivot->asset_model_id == $modelId;
}
)->map(
function ($item) {
return $item->pivot->default_value;
}
)->first();
}
/**
* Checks the format of the attribute
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param $value string
* @since [v3.0]
* @param $value string
* @since [v3.0]
* @return bool
*/
public function check_format($value)
@@ -286,7 +302,7 @@ class CustomField extends Model
* Gets the DB column name.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return string
*/
public function db_column_name()
@@ -302,7 +318,7 @@ class CustomField extends Model
* user-friendly text in the dropdowns, and in the custom fields display.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @since [v3.4]
* @return string
*/
public function getFormatAttribute($value)
@@ -320,7 +336,7 @@ class CustomField extends Model
* Format a value string as an array for select boxes and checkboxes.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @since [v3.4]
* @return array
*/
public function setFormatAttribute($value)
@@ -336,7 +352,7 @@ class CustomField extends Model
* Format a value string as an array for select boxes and checkboxes.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @since [v3.4]
* @return array
*/
public function formatFieldValuesAsArray()
@@ -366,7 +382,7 @@ class CustomField extends Model
* Check whether the field is encrypted
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @since [v3.4]
* @return bool
*/
public function isFieldDecryptable($string)
@@ -383,7 +399,7 @@ class CustomField extends Model
* won't break the database.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @since [v3.4]
* @return string
*/
public function convertUnicodeDbSlug($original = null)
@@ -392,7 +408,7 @@ class CustomField extends Model
$id = $this->id ? $this->id : 'xx';
if (! function_exists('transliterator_transliterate')) {
$long_slug = '_snipeit_'.str_slug(mb_convert_encoding(trim($name),"UTF-8"), '_');
$long_slug = '_snipeit_'.str_slug(mb_convert_encoding(trim($name), "UTF-8"), '_');
} else {
$long_slug = '_snipeit_'.Utf8Slugger::slugify($name, '_');
}
@@ -402,9 +418,10 @@ class CustomField extends Model
/**
* Get validation rules for custom fields to use with Validator
*
* @author [V. Cordes] [<volker@fdatek.de>]
* @param int $id
* @since [v4.1.10]
* @param int $id
* @since [v4.1.10]
* @return array
*/
public function validationRules($regex_format = null)
@@ -418,6 +435,7 @@ class CustomField extends Model
/**
* Check to see if there is a custom regex format type
*
* @see https://github.com/grokability/snipe-it/issues/5896
*
* @author Wes Hulette <jwhulette@gmail.com>

View File

@@ -20,6 +20,7 @@ class CustomFieldset extends Model
/**
* Validation rules
*
* @var array
*/
public $rules = [
@@ -39,7 +40,7 @@ class CustomFieldset extends Model
* Establishes the fieldset -> field relationship
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function fields()
@@ -51,7 +52,7 @@ class CustomFieldset extends Model
* Establishes the fieldset -> models relationship
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function models()
@@ -63,7 +64,7 @@ class CustomFieldset extends Model
* Establishes the fieldset -> admin user relationship
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function user()
@@ -76,14 +77,14 @@ class CustomFieldset extends Model
if ($this->fields) {
switch ($form_type) {
case 'audit':
return $this->fields->where('display_audit', '1')->count() > 0;
case 'checkin':
return $this->fields->where('display_checkin', '1')->count() > 0;
case 'checkout':
return $this->fields->where('display_checkout', '1')->count() > 0;
default:
return true;
case 'audit':
return $this->fields->where('display_audit', '1')->count() > 0;
case 'checkin':
return $this->fields->where('display_checkin', '1')->count() > 0;
case 'checkout':
return $this->fields->where('display_checkout', '1')->count() > 0;
default:
return true;
}
}
@@ -95,7 +96,7 @@ class CustomFieldset extends Model
* custom field format
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @since [v3.0]
* @return array
*/
public function validation_rules()
@@ -104,8 +105,9 @@ class CustomFieldset extends Model
foreach ($this->fields as $field) {
$rule = [];
if (($field->field_encrypted != '1') ||
(($field->field_encrypted == '1') && (Gate::allows('admin')))) {
if (($field->field_encrypted != '1')
|| (($field->field_encrypted == '1') && (Gate::allows('admin')))
) {
$rule[] = ($field->pivot->required == '1') ? 'required' : 'nullable';
}

View File

@@ -72,7 +72,7 @@ class Department extends SnipeModel
* Establishes the department -> company relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company()
@@ -84,7 +84,7 @@ class Department extends SnipeModel
* Establishes the department -> users relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function users()
@@ -96,7 +96,7 @@ class Department extends SnipeModel
* Establishes the department -> manager relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manager()
@@ -108,7 +108,7 @@ class Department extends SnipeModel
* Establishes the department -> location relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location()
@@ -119,8 +119,8 @@ class Department extends SnipeModel
/**
* Query builder scope to order on location name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -132,8 +132,8 @@ class Department extends SnipeModel
/**
* Query builder scope to order on manager name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
@@ -145,8 +145,8 @@ class Department extends SnipeModel
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/

View File

@@ -48,15 +48,15 @@ class Depreciable extends SnipeModel
$depreciation = 0;
$setting = Setting::getSettings();
switch ($setting->depreciation_method) {
case 'half_1':
case 'half_1':
$depreciation = $this->getHalfYearDepreciatedValue(true);
break;
case 'half_2':
case 'half_2':
$depreciation = $this->getHalfYearDepreciatedValue(false);
break;
default:
default:
$depreciation = $this->getLinearDepreciatedValue();
}
@@ -74,7 +74,7 @@ class Depreciable extends SnipeModel
return null;
}
if ($months_passed >= $this->get_depreciation()->months){
if ($months_passed >= $this->get_depreciation()->months) {
//if there is a floor use it
if($this->get_depreciation()->depreciation_min) {
@@ -93,14 +93,15 @@ class Depreciable extends SnipeModel
return $current_value;
}
public function getMonthlyDepreciation(){
public function getMonthlyDepreciation()
{
return ($this->purchase_cost-$this->calculateDepreciation())/$this->get_depreciation()->months;
}
/**
* @param onlyHalfFirstYear Boolean always applied only second half of the first year
* @param onlyHalfFirstYear Boolean always applied only second half of the first year
* @return float|int
*/
public function getHalfYearDepreciatedValue($onlyHalfFirstYear = false)
@@ -131,7 +132,7 @@ class Depreciable extends SnipeModel
}
/**
* @param \DateTime $date
* @param \DateTime $date
* @return int
*/
protected function get_fiscal_year($date)
@@ -146,7 +147,7 @@ class Depreciable extends SnipeModel
}
/**
* @param \DateTime $date
* @param \DateTime $date
* @return bool
*/
protected function is_first_half_of_year($date)

View File

@@ -16,7 +16,7 @@ class Depreciation extends SnipeModel
// Declare the rules for the form validation
protected $rules = [
'name' => 'required|min:3|max:255|unique:depreciations,name',
'months' => 'required|max:3600|integer|gt:0',
'months' => 'required|max:3600|integer',
];
/**
@@ -56,7 +56,7 @@ class Depreciation extends SnipeModel
* Establishes the depreciation -> models relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v5.0]
* @since [v5.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function models()
@@ -68,7 +68,7 @@ class Depreciation extends SnipeModel
* Establishes the depreciation -> licenses relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v5.0]
* @since [v5.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenses()
@@ -80,7 +80,7 @@ class Depreciation extends SnipeModel
* Establishes the depreciation -> assets relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v5.0]
* @since [v5.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets()
@@ -92,7 +92,7 @@ class Depreciation extends SnipeModel
* Get the user that created the depreciation
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v7.0.13]
* @since [v7.0.13]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()

View File

@@ -51,7 +51,7 @@ class Group extends SnipeModel
* Establishes the groups -> users relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function users()
@@ -63,7 +63,7 @@ class Group extends SnipeModel
* Get the user that created the group
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v6.3.0]
* @since [v6.3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
@@ -75,7 +75,7 @@ class Group extends SnipeModel
* Decode JSON permissions into array
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @since [v1.0]
* @return array | \stdClass
*/
public function decodePermissions()

View File

@@ -19,7 +19,7 @@ class Import extends Model
* Establishes the license -> admin user relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()

View File

@@ -38,7 +38,8 @@ class DefaultLabel extends RectangleSheet
private int $rows;
public function __construct() {
public function __construct()
{
$settings = Setting::getSettings();
$this->textSize = Helper::convertUnit($settings->labels_fontsize, 'pt', 'in');
@@ -74,41 +75,116 @@ class DefaultLabel extends RectangleSheet
}
public function getUnit() { return 'in'; }
public function getUnit()
{
return 'in';
}
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageWidth()
{
return $this->pageWidth;
}
public function getPageHeight()
{
return $this->pageHeight;
}
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginBottom; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginRight; }
public function getPageMarginTop()
{
return $this->pageMarginTop;
}
public function getPageMarginBottom()
{
return $this->pageMarginBottom;
}
public function getPageMarginLeft()
{
return $this->pageMarginLeft;
}
public function getPageMarginRight()
{
return $this->pageMarginRight;
}
public function getColumns() { return $this->columns; }
public function getRows() { return $this->rows; }
public function getLabelBorder() { return 0; }
public function getColumns()
{
return $this->columns;
}
public function getRows()
{
return $this->rows;
}
public function getLabelBorder()
{
return 0;
}
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelWidth()
{
return $this->labelWidth;
}
public function getLabelHeight()
{
return $this->labelHeight;
}
public function getLabelMarginTop() { return 0; }
public function getLabelMarginBottom() { return 0; }
public function getLabelMarginLeft() { return 0; }
public function getLabelMarginRight() { return 0; }
public function getLabelMarginTop()
{
return 0;
}
public function getLabelMarginBottom()
{
return 0;
}
public function getLabelMarginLeft()
{
return 0;
}
public function getLabelMarginRight()
{
return 0;
}
public function getLabelColumnSpacing() { return $this->labelSpacingH; }
public function getLabelRowSpacing() { return $this->labelSpacingV; }
public function getLabelColumnSpacing()
{
return $this->labelSpacingH;
}
public function getLabelRowSpacing()
{
return $this->labelSpacingV;
}
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 4; }
public function getSupportTitle() { return true; }
public function getSupportLogo() { return true; }
public function getSupportAssetTag()
{
return false;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 4;
}
public function getSupportTitle()
{
return true;
}
public function getSupportLogo()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$asset = $record->get('asset');
$settings = Setting::getSettings();

View File

@@ -5,21 +5,30 @@ namespace App\Models\Labels;
use App\Models\Asset;
use Illuminate\Support\Collection;
class Field {
class Field
{
protected Collection $options;
public function getOptions() { return $this->options; }
public function setOptions($options) {
public function getOptions()
{
return $this->options;
}
public function setOptions($options)
{
$tempCollect = collect($options);
if (!$tempCollect->contains(fn($o) => !is_subclass_of($o, FieldOption::class))) {
$this->options = $options;
}
}
public function toArray(Asset $asset) { return Field::makeArray($this, $asset); }
public function toArray(Asset $asset)
{
return Field::makeArray($this, $asset);
}
/* Statics */
public static function makeArray(Field $field, Asset $asset) {
public static function makeArray(Field $field, Asset $asset)
{
return $field->getOptions()
// filter out any FieldOptions that are accidentally null
->filter()
@@ -27,11 +36,13 @@ class Field {
->filter(fn($result) => $result['value'] != null);
}
public static function makeString(Field $option) {
public static function makeString(Field $option)
{
return implode('|', $option->getOptions());
}
public static function fromString(string $theString) {
public static function fromString(string $theString)
{
$field = new Field();
$field->options = collect(explode('|', $theString))
->filter(fn($optionString) => !empty($optionString))

View File

@@ -5,14 +5,22 @@ namespace App\Models\Labels;
use App\Models\Asset;
use Illuminate\Support\Collection;
class FieldOption {
class FieldOption
{
protected string $label;
public function getLabel() { return $this->label; }
public function getLabel()
{
return $this->label;
}
protected string $dataSource;
public function getDataSource() { return $this->dataSource; }
public function getDataSource()
{
return $this->dataSource;
}
public function getValue(Asset $asset) {
public function getValue(Asset $asset)
{
$dataPath = collect(explode('.', $this->dataSource));
// assignedTo directly on the asset is a special case where
@@ -33,18 +41,29 @@ class FieldOption {
return $asset->purchase_date ? $asset->purchase_date->format('Y-m-d') : null;
}
return $dataPath->reduce(function ($myValue, $path) {
try { return $myValue ? $myValue->{$path} : ${$myValue}; }
catch (\Exception $e) { return $myValue; }
}, $asset);
return $dataPath->reduce(
function ($myValue, $path) {
try { return $myValue ? $myValue->{$path} : ${$myValue};
}
catch (\Exception $e) { return $myValue;
}
}, $asset
);
}
public function toArray(Asset $asset=null) { return FieldOption::makeArray($this, $asset); }
public function toString() { return FieldOption::makeString($this); }
public function toArray(Asset $asset=null)
{
return FieldOption::makeArray($this, $asset);
}
public function toString()
{
return FieldOption::makeString($this);
}
/* Statics */
public static function makeArray(FieldOption $option, Asset $asset=null) {
public static function makeArray(FieldOption $option, Asset $asset=null)
{
return [
'label' => $option->getLabel(),
'dataSource' => $option->getDataSource(),
@@ -52,11 +71,13 @@ class FieldOption {
];
}
public static function makeString(FieldOption $option) {
public static function makeString(FieldOption $option)
{
return $option->getLabel() . '=' . $option->getDataSource();
}
public static function fromString(string $theString) {
public static function fromString(string $theString)
{
$parts = explode('=', $theString);
if (count($parts) == 2) {
$option = new FieldOption();

View File

@@ -13,7 +13,7 @@ use Illuminate\Support\Facades\Log;
/**
* Model for Labels.
*
* @version v1.0
* @version v1.0
*/
abstract class Label
{
@@ -32,7 +32,8 @@ abstract class Label
*
* @return int
*/
public function getRotation() {
public function getRotation()
{
return 0;
}
@@ -123,29 +124,32 @@ abstract class Label
/**
* Make changes to the PDF properties here. OPTIONAL.
*
* @param TCPDF $pdf The TCPDF instance
* @param TCPDF $pdf The TCPDF instance
*/
public abstract function preparePDF(TCPDF $pdf);
/**
* Write single data record as content here.
*
* @param TCPDF $pdf The TCPDF instance
* @param Collection $record A data record
* @param TCPDF $pdf The TCPDF instance
* @param Collection $record A data record
*/
public abstract function write(TCPDF $pdf, Collection $record);
/**
* Handle the data here. Override for multiple-per-page handling
*
* @param TCPDF $pdf The TCPDF instance
* @param Collection $data The data
* @param TCPDF $pdf The TCPDF instance
* @param Collection $data The data
*/
public function writeAll(TCPDF $pdf, Collection $data) {
$data->each(function ($record, $index) use ($pdf) {
$pdf->AddPage();
$this->write($pdf, $record);
});
public function writeAll(TCPDF $pdf, Collection $data)
{
$data->each(
function ($record, $index) use ($pdf) {
$pdf->AddPage();
$this->write($pdf, $record);
}
);
}
/**
@@ -153,7 +157,8 @@ abstract class Label
*
* @return string
*/
public final function getName() {
public final function getName()
{
$refClass = new \ReflectionClass(Label::class);
return str_replace($refClass->getNamespaceName() . '\\', '', get_class($this));
}
@@ -165,7 +170,8 @@ abstract class Label
*
* @return string
*/
public final function getOrientation() {
public final function getOrientation()
{
return ($this->getWidth() >= $this->getHeight()) ? 'L' : 'P';
}
@@ -174,7 +180,8 @@ abstract class Label
*
* @return object [ 'x1'=>0.00, 'y1'=>0.00, 'x2'=>0.00, 'y2'=>0.00, 'w'=>0.00, 'h'=>0.00 ]
*/
public final function getPrintableArea() {
public final function getPrintableArea()
{
return (object)[
'x1' => $this->getMarginLeft(),
'y1' => $this->getMarginTop(),
@@ -188,21 +195,22 @@ abstract class Label
/**
* Write a text cell.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $text The text to write. Supports 'some **bold** text'.
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param string $font The font family
* @param string $style The font style
* @param int $size The font size in getUnit() units
* @param string $align Align text in the box. 'L' left, 'R' right, 'C' center.
* @param float $width Force text box width. NULL to auto-fit.
* @param float $height Force text box height. NULL to auto-fit.
* @param bool $squash Squash text if it's too big
* @param int $border Thickness of border. Default = 0.
* @param int $spacing Letter spacing. Default = 0.
* @param TCPDF $pdf The TCPDF instance
* @param string $text The text to write. Supports 'some **bold** text'.
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param string $font The font family
* @param string $style The font style
* @param int $size The font size in getUnit() units
* @param string $align Align text in the box. 'L' left, 'R' right, 'C' center.
* @param float $width Force text box width. NULL to auto-fit.
* @param float $height Force text box height. NULL to auto-fit.
* @param bool $squash Squash text if it's too big
* @param int $border Thickness of border. Default = 0.
* @param int $spacing Letter spacing. Default = 0.
*/
public final function writeText(TCPDF $pdf, $text, $x, $y, $font=null, $style=null, $size=null, $align='L', $width=null, $height=null, $squash=false, $border=0, $spacing=0) {
public final function writeText(TCPDF $pdf, $text, $x, $y, $font=null, $style=null, $size=null, $align='L', $width=null, $height=null, $squash=false, $border=0, $spacing=0)
{
$prevFamily = $pdf->getFontFamily();
$prevStyle = $pdf->getFontStyle();
$prevSizePt = $pdf->getFontSizePt();
@@ -211,33 +219,42 @@ abstract class Label
$fontFamily = !empty($font) ? $font : $prevFamily;
$fontStyle = !empty($style) ? $style : $prevStyle;
if ($size) $fontSizePt = Helper::convertUnit($size, $this->getUnit(), 'pt', true);
else $fontSizePt = $prevSizePt;
if ($size) { $fontSizePt = Helper::convertUnit($size, $this->getUnit(), 'pt', true);
} else { $fontSizePt = $prevSizePt;
}
$pdf->SetFontSpacing($spacing);
$parts = collect(explode('**', $text))
->map(function ($part, $index) use ($pdf, $fontFamily, $fontStyle, $fontSizePt) {
$modStyle = ($index % 2 == 1) ? 'B' : $fontStyle;
$pdf->setFont($fontFamily, $modStyle, $fontSizePt);
return [
->map(
function ($part, $index) use ($pdf, $fontFamily, $fontStyle, $fontSizePt) {
$modStyle = ($index % 2 == 1) ? 'B' : $fontStyle;
$pdf->setFont($fontFamily, $modStyle, $fontSizePt);
return [
'text' => $part,
'text_width' => $pdf->GetStringWidth($part),
'font_family' => $fontFamily,
'font_style' => $modStyle,
'font_size' => $fontSizePt,
];
});
];
}
);
$textWidth = $parts->reduce(function ($carry, $part) { return $carry += $part['text_width']; });
$textWidth = $parts->reduce(
function ($carry, $part) {
return $carry += $part['text_width'];
}
);
$cellWidth = !empty($width) ? $width : $textWidth;
if ($squash && ($textWidth > 0)) {
$scaleFactor = min(1.0, $cellWidth / $textWidth);
$parts = $parts->map(function ($part, $index) use ($scaleFactor) {
$part['text_width'] = $part['text_width'] * $scaleFactor;
return $part;
});
$parts = $parts->map(
function ($part, $index) use ($scaleFactor) {
$part['text_width'] = $part['text_width'] * $scaleFactor;
return $part;
}
);
}
$cellHeight = !empty($height) ? $height : Helper::convertUnit($fontSizePt, 'pt', $this->getUnit());
@@ -249,18 +266,23 @@ abstract class Label
}
switch($align) {
case 'R': $startX = ($x + $cellWidth) - min($cellWidth, $textWidth); break;
case 'C': $startX = ($x + ($cellWidth / 2)) - (min($cellWidth, $textWidth) / 2); break;
case 'L':
default: $startX = $x; break;
case 'R': $startX = ($x + $cellWidth) - min($cellWidth, $textWidth);
break;
case 'C': $startX = ($x + ($cellWidth / 2)) - (min($cellWidth, $textWidth) / 2);
break;
case 'L':
default: $startX = $x;
break;
}
$parts->reduce(function ($currentX, $part) use ($pdf, $y, $cellHeight) {
$pdf->SetXY($currentX, $y);
$pdf->setFont($part['font_family'], $part['font_style'], $part['font_size']);
$pdf->Cell($part['text_width'], $cellHeight, $part['text'], 0, 0, '', false, '', 1, true);
return $currentX += $part['text_width'];
}, $startX);
$parts->reduce(
function ($currentX, $part) use ($pdf, $y, $cellHeight) {
$pdf->SetXY($currentX, $y);
$pdf->setFont($part['font_family'], $part['font_style'], $part['font_size']);
$pdf->Cell($part['text_width'], $cellHeight, $part['text'], 0, 0, '', false, '', 1, true);
return $currentX += $part['text_width'];
}, $startX
);
$pdf->SetFont($prevFamily, $prevStyle, $prevSizePt);
$pdf->SetFontSpacing(0);
@@ -269,27 +291,30 @@ abstract class Label
/**
* Write an image.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $image The image to write
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
* @param string $halign Align text in the box. 'L' left, 'R' right, 'C' center. Default 'L'.
* @param string $valign Align text in the box. 'T' top, 'B' bottom, 'C' center. Default 'T'.
* @param int $dpi Pixels per inch
* @param bool $resize Resize to fit container
* @param bool $stretch Stretch (vs Scale) to fit container
* @param int $border Thickness of border. Default = 0.
* @param TCPDF $pdf The TCPDF instance
* @param string $image The image to write
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
* @param string $halign Align text in the box. 'L' left, 'R' right, 'C' center. Default 'L'.
* @param string $valign Align text in the box. 'T' top, 'B' bottom, 'C' center. Default 'T'.
* @param int $dpi Pixels per inch
* @param bool $resize Resize to fit container
* @param bool $stretch Stretch (vs Scale) to fit container
* @param int $border Thickness of border. Default = 0.
*
* @return array Returns the final calculated size [w,h]
*/
public final function writeImage(TCPDF $pdf, $image, $x, $y, $width=null, $height=null, $halign='L', $valign='L', $dpi=300, $resize=false, $stretch=false, $border=0) {
public final function writeImage(TCPDF $pdf, $image, $x, $y, $width=null, $height=null, $halign='L', $valign='L', $dpi=300, $resize=false, $stretch=false, $border=0)
{
if (empty($image)) return [0,0];
if (empty($image)) { return [0,0];
}
$imageInfo = getimagesize($image);
if (!$imageInfo) return [0,0]; // TODO: SVG or other
if (!$imageInfo) { return [0,0]; // TODO: SVG or other
}
$imageWidthPx = $imageInfo[0];
$imageHeightPx = $imageInfo[1];
@@ -342,18 +367,24 @@ abstract class Label
// Horizontal Position
switch ($halign) {
case 'R': $originX = ($x + $containerWidth) - $outputWidth; break;
case 'C': $originX = ($x + ($containerWidth / 2)) - ($outputWidth / 2); break;
case 'L':
default: $originX = $x; break;
case 'R': $originX = ($x + $containerWidth) - $outputWidth;
break;
case 'C': $originX = ($x + ($containerWidth / 2)) - ($outputWidth / 2);
break;
case 'L':
default: $originX = $x;
break;
}
// Vertical Position
switch ($valign) {
case 'B': $originY = ($y + $containerHeight) - $outputHeight; break;
case 'C': $originY = ($y + ($containerHeight / 2)) - ($outputHeight / 2); break;
case 'T':
default: $originY = $y; break;
case 'B': $originY = ($y + $containerHeight) - $outputHeight;
break;
case 'C': $originY = ($y + ($containerHeight / 2)) - ($outputHeight / 2);
break;
case 'T':
default: $originY = $y;
break;
}
// Actual Image
@@ -373,16 +404,18 @@ abstract class Label
/**
* Write a 1D barcode.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $value The barcode content
* @param string $type The barcode type
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
* @param TCPDF $pdf The TCPDF instance
* @param string $value The barcode content
* @param string $type The barcode type
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
*/
public final function write1DBarcode(TCPDF $pdf, $value, $type, $x, $y, $width, $height) {
if (empty($value)) return;
public final function write1DBarcode(TCPDF $pdf, $value, $type, $x, $y, $width, $height)
{
if (empty($value)) { return;
}
try {
$pdf->write1DBarcode($value, $type, $x, $y, $width, $height, null, ['stretch'=>true]);
} catch (\Exception|TypeError $e) {
@@ -393,16 +426,18 @@ abstract class Label
/**
* Write a 2D barcode.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $value The barcode content
* @param string $type The barcode type
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
* @param TCPDF $pdf The TCPDF instance
* @param string $value The barcode content
* @param string $type The barcode type
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
*/
public final function write2DBarcode(TCPDF $pdf, $value, $type, $x, $y, $width, $height) {
if (empty($value)) return;
public final function write2DBarcode(TCPDF $pdf, $value, $type, $x, $y, $width, $height)
{
if (empty($value)) { return;
}
$pdf->write2DBarcode($value, $type, $x, $y, $width, $height, null, ['stretch'=>true]);
}
@@ -411,127 +446,180 @@ abstract class Label
/**
* Checks the template is internally valid
*/
public final function validate() : void {
public final function validate() : void
{
$this->validateUnits();
$this->validateSize();
$this->validateMargins();
$this->validateSupport();
}
private function validateUnits() : void {
private function validateUnits() : void
{
$validUnits = [ 'pt', 'mm', 'cm', 'in' ];
$unit = $this->getUnit();
if (!in_array(strtolower($unit), $validUnits)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_value', [
'name' => 'getUnit()',
'expected' => '[ \''.implode('\', \'', $validUnits).'\' ]',
'actual' => '\''.$unit.'\''
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_value', [
'name' => 'getUnit()',
'expected' => '[ \''.implode('\', \'', $validUnits).'\' ]',
'actual' => '\''.$unit.'\''
]
)
);
}
}
private function validateSize() : void {
private function validateSize() : void
{
$width = $this->getWidth();
if (!is_numeric($width) || is_string($width)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getWidth()',
'expected' => 'float',
'actual' => gettype($width)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getWidth()',
'expected' => 'float',
'actual' => gettype($width)
]
)
);
}
$height = $this->getHeight();
if (!is_numeric($height) || is_string($height)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getHeight()',
'expected' => 'float',
'actual' => gettype($height)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getHeight()',
'expected' => 'float',
'actual' => gettype($height)
]
)
);
}
}
private function validateMargins() : void {
private function validateMargins() : void
{
$marginTop = $this->getMarginTop();
if (!is_numeric($marginTop) || is_string($marginTop)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginTop()',
'expected' => 'float',
'actual' => gettype($marginTop)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getMarginTop()',
'expected' => 'float',
'actual' => gettype($marginTop)
]
)
);
}
$marginBottom = $this->getMarginBottom();
if (!is_numeric($marginBottom) || is_string($marginBottom)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginBottom()',
'expected' => 'float',
'actual' => gettype($marginBottom)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getMarginBottom()',
'expected' => 'float',
'actual' => gettype($marginBottom)
]
)
);
}
$marginLeft = $this->getMarginLeft();
if (!is_numeric($marginLeft) || is_string($marginLeft)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginLeft()',
'expected' => 'float',
'actual' => gettype($marginLeft)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getMarginLeft()',
'expected' => 'float',
'actual' => gettype($marginLeft)
]
)
);
}
$marginRight = $this->getMarginRight();
if (!is_numeric($marginRight) || is_string($marginRight)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginRight()',
'expected' => 'float',
'actual' => gettype($marginRight)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getMarginRight()',
'expected' => 'float',
'actual' => gettype($marginRight)
]
)
);
}
}
private function validateSupport() : void {
private function validateSupport() : void
{
$support1D = $this->getSupport1DBarcode();
if (!is_bool($support1D)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupport1DBarcode()',
'expected' => 'boolean',
'actual' => gettype($support1D)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getSupport1DBarcode()',
'expected' => 'boolean',
'actual' => gettype($support1D)
]
)
);
}
$support2D = $this->getSupport2DBarcode();
if (!is_bool($support2D)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupport2DBarcode()',
'expected' => 'boolean',
'actual' => gettype($support2D)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getSupport2DBarcode()',
'expected' => 'boolean',
'actual' => gettype($support2D)
]
)
);
}
$supportFields = $this->getSupportFields();
if (!is_int($supportFields)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupportFields()',
'expected' => 'integer',
'actual' => gettype($supportFields)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getSupportFields()',
'expected' => 'integer',
'actual' => gettype($supportFields)
]
)
);
}
$supportLogo = $this->getSupportLogo();
if (!is_bool($supportLogo)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupportLogo()',
'expected' => 'boolean',
'actual' => gettype($supportLogo)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getSupportLogo()',
'expected' => 'boolean',
'actual' => gettype($supportLogo)
]
)
);
}
$supportTitle = $this->getSupportTitle();
if (!is_bool($supportTitle)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupportTitle()',
'expected' => 'boolean',
'actual' => gettype($supportTitle)
]));
throw new \UnexpectedValueException(
trans(
'admin/labels/message.invalid_return_type', [
'name' => 'getSupportTitle()',
'expected' => 'boolean',
'actual' => gettype($supportTitle)
]
)
);
}
}
@@ -539,23 +627,26 @@ abstract class Label
/**
* Public Static Functions
*/
*/
/**
* Find size of a page by its format.
*
* @param string $format Format name (eg: 'A4', 'LETTER', etc.)
* @param string $orientation 'L' for Landscape, 'P' for Portrait ('L' default)
* @param string $unit Unit of measure to return in ('mm' default)
* @param string $format Format name (eg: 'A4', 'LETTER', etc.)
* @param string $orientation 'L' for Landscape, 'P' for Portrait ('L' default)
* @param string $unit Unit of measure to return in ('mm' default)
*
* @return object (object)[ 'width' => (float)123.4, 'height' => (float)123.4 ]
*/
public static function fromFormat($format, $orientation='L', $unit='mm', $round=false) {
public static function fromFormat($format, $orientation='L', $unit='mm', $round=false)
{
$size = collect(TCPDF_STATIC::getPageSizeFromFormat(strtoupper($format)))
->sort()
->map(function ($value) use ($unit) {
return Helper::convertUnit($value, 'pt', $unit);
})
->map(
function ($value) use ($unit) {
return Helper::convertUnit($value, 'pt', $unit);
}
)
->toArray();
$width = ($orientation == 'L') ? $size[1] : $size[0];
$height = ($orientation == 'L') ? $size[0] : $size[1];
@@ -571,16 +662,19 @@ abstract class Label
* Unlike most Models, these are defined by their existence as non-
* abstract classes stored in Models\Labels.
*
* @param string|Arrayable|array|null $path Label path[s]
* @param string|Arrayable|array|null $path Label path[s]
* @return Collection|Label|null
*/
public static function find($name=null) {
public static function find($name=null)
{
// Find many
if (is_array($name) || $name instanceof Arrayable) {
$labels = collect($name)
->map(function ($thisname) {
return static::find($thisname);
})
->map(
function ($thisname) {
return static::find($thisname);
}
)
->whereNotNull();
return ($labels->count() > 0) ? $labels : null;
}
@@ -588,26 +682,36 @@ abstract class Label
// Find one
if ($name !== null) {
return static::find()
->sole(function ($label) use ($name) {
return $label->getName() == $name;
});
->sole(
function ($label) use ($name) {
return $label->getName() == $name;
}
);
}
// Find all
return collect(File::allFiles(__DIR__))
->map(function ($file) {
preg_match_all('/\/*(.+?)(?:\/|\.)/', $file->getRelativePathName(), $matches);
return __NAMESPACE__ . '\\' . implode('\\', $matches[1]);
})
->filter(function ($name) {
if (!class_exists($name)) return false;
$refClass = new \ReflectionClass($name);
if ($refClass->isAbstract()) return false;
return $refClass->isSubclassOf(Label::class);
})
->map(function ($name) {
return new $name();
});
->map(
function ($file) {
preg_match_all('/\/*(.+?)(?:\/|\.)/', $file->getRelativePathName(), $matches);
return __NAMESPACE__ . '\\' . implode('\\', $matches[1]);
}
)
->filter(
function ($name) {
if (!class_exists($name)) { return false;
}
$refClass = new \ReflectionClass($name);
if ($refClass->isAbstract()) { return false;
}
return $refClass->isSubclassOf(Label::class);
}
)
->map(
function ($name) {
return new $name();
}
);
}

View File

@@ -33,9 +33,13 @@ abstract class RectangleSheet extends Sheet
public abstract function getLabelRowSpacing();
public function getLabelsPerPage() { return $this->getColumns() * $this->getRows(); }
public function getLabelsPerPage()
{
return $this->getColumns() * $this->getRows();
}
public function getLabelPosition($index) {
public function getLabelPosition($index)
{
$printIndex = $index + $this->getLabelIndexOffset();
$row = (int)($printIndex / $this->getColumns());
$col = $printIndex - ($row * $this->getColumns());

View File

@@ -6,12 +6,30 @@ abstract class Sheet extends Label
{
protected int $indexOffset = 0;
public function getWidth() { return $this->getPageWidth(); }
public function getHeight() { return $this->getPageHeight(); }
public function getMarginTop() { return $this->getPageMarginTop(); }
public function getMarginBottom() { return $this->getPageMarginBottom(); }
public function getMarginLeft() { return $this->getPageMarginLeft(); }
public function getMarginRight() { return $this->getPageMarginRight(); }
public function getWidth()
{
return $this->getPageWidth();
}
public function getHeight()
{
return $this->getPageHeight();
}
public function getMarginTop()
{
return $this->getPageMarginTop();
}
public function getMarginBottom()
{
return $this->getPageMarginBottom();
}
public function getMarginLeft()
{
return $this->getPageMarginLeft();
}
public function getMarginRight()
{
return $this->getPageMarginRight();
}
/**
* Returns the page width in getUnit() units
@@ -107,7 +125,7 @@ abstract class Sheet extends Label
/**
* Returns label position based on its index
*
* @param int $index
* @param int $index
*
* @return array [x,y]
*/
@@ -123,10 +141,11 @@ abstract class Sheet extends Label
/**
* Handle the data here. Override for multiple-per-page handling
*
* @param TCPDF $pdf The TCPDF instance
* @param Collection $data The data
* @param TCPDF $pdf The TCPDF instance
* @param Collection $data The data
*/
public function writeAll($pdf, $data) {
public function writeAll($pdf, $data)
{
$prevPageNumber = -1;
foreach ($data->toArray() as $recordIndex => $record) {
@@ -170,7 +189,8 @@ abstract class Sheet extends Label
*
* @return string
*/
public final function getLabelOrientation() {
public final function getLabelOrientation()
{
return ($this->getLabelWidth() >= $this->getLabelHeight()) ? 'L' : 'P';
}
@@ -179,7 +199,8 @@ abstract class Sheet extends Label
*
* @return object [ 'x1'=>0.00, 'y1'=>0.00, 'x2'=>0.00, 'y2'=>0.00, 'w'=>0.00, 'h'=>0.00 ]
*/
public final function getLabelPrintableArea() {
public final function getLabelPrintableArea()
{
return (object)[
'x1' => $this->getLabelMarginLeft(),
'y1' => $this->getLabelMarginTop(),
@@ -195,15 +216,20 @@ abstract class Sheet extends Label
*
* @return int
*/
public function getLabelIndexOffset() { return $this->indexOffset; }
public function getLabelIndexOffset()
{
return $this->indexOffset;
}
/**
* Sets label index offset (skip positions)
*
* @param int $offset
*
* @param int $offset
*/
public function setLabelIndexOffset(int $offset) { $this->indexOffset = $offset; }
public function setLabelIndexOffset(int $offset)
{
$this->indexOffset = $offset;
}
}
?>

View File

@@ -31,7 +31,8 @@ abstract class L7162 extends RectangleSheet
private float $labelWidth;
private float $labelHeight;
public function __construct() {
public function __construct()
{
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 0);
$this->pageWidth = $paperSize->width;
$this->pageHeight = $paperSize->height;
@@ -48,24 +49,63 @@ abstract class L7162 extends RectangleSheet
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
}
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageWidth()
{
return $this->pageWidth;
}
public function getPageHeight()
{
return $this->pageHeight;
}
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginTop; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginLeft; }
public function getPageMarginTop()
{
return $this->pageMarginTop;
}
public function getPageMarginBottom()
{
return $this->pageMarginTop;
}
public function getPageMarginLeft()
{
return $this->pageMarginLeft;
}
public function getPageMarginRight()
{
return $this->pageMarginLeft;
}
public function getColumns() { return 2; }
public function getRows() { return 8; }
public function getColumns()
{
return 2;
}
public function getRows()
{
return 8;
}
public function getLabelColumnSpacing() { return $this->columnSpacing; }
public function getLabelRowSpacing() { return $this->rowSpacing; }
public function getLabelColumnSpacing()
{
return $this->columnSpacing;
}
public function getLabelRowSpacing()
{
return $this->rowSpacing;
}
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelWidth()
{
return $this->labelWidth;
}
public function getLabelHeight()
{
return $this->labelHeight;
}
public function getLabelBorder() { return 0; }
public function getLabelBorder()
{
return 0;
}
}
?>

View File

@@ -14,23 +14,59 @@ class L7162_A extends L7162
private const FIELD_SIZE = 4.60;
private const FIELD_MARGIN = 0.30;
public function getUnit() { return 'mm'; }
public function getUnit()
{
return 'mm';
}
public function getLabelMarginTop() { return 1.0; }
public function getLabelMarginBottom() { return 1.0; }
public function getLabelMarginLeft() { return 1.0; }
public function getLabelMarginRight() { return 1.0; }
public function getLabelMarginTop()
{
return 1.0;
}
public function getLabelMarginBottom()
{
return 1.0;
}
public function getLabelMarginLeft()
{
return 1.0;
}
public function getLabelMarginRight()
{
return 1.0;
}
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 4; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 4;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
$usableWidth = $pa->w;

View File

@@ -17,23 +17,59 @@ class L7162_B extends L7162
private const FIELD_SIZE = 4.20;
private const FIELD_MARGIN = 0.30;
public function getUnit() { return 'mm'; }
public function getUnit()
{
return 'mm';
}
public function getLabelMarginTop() { return 1.0; }
public function getLabelMarginBottom() { return 0; }
public function getLabelMarginLeft() { return 1.0; }
public function getLabelMarginRight() { return 1.0; }
public function getLabelMarginTop()
{
return 1.0;
}
public function getLabelMarginBottom()
{
return 0;
}
public function getLabelMarginLeft()
{
return 1.0;
}
public function getLabelMarginRight()
{
return 1.0;
}
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return false; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return true; }
public function getSupportTitle() { return true; }
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return false;
}
public function getSupportFields()
{
return 3;
}
public function getSupportLogo()
{
return true;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
$usableWidth = $pa->w;

View File

@@ -31,7 +31,8 @@ abstract class L7163 extends RectangleSheet
private float $labelWidth;
private float $labelHeight;
public function __construct() {
public function __construct()
{
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 0);
$this->pageWidth = $paperSize->width;
$this->pageHeight = $paperSize->height;
@@ -48,24 +49,63 @@ abstract class L7163 extends RectangleSheet
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
}
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageWidth()
{
return $this->pageWidth;
}
public function getPageHeight()
{
return $this->pageHeight;
}
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginTop; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginLeft; }
public function getPageMarginTop()
{
return $this->pageMarginTop;
}
public function getPageMarginBottom()
{
return $this->pageMarginTop;
}
public function getPageMarginLeft()
{
return $this->pageMarginLeft;
}
public function getPageMarginRight()
{
return $this->pageMarginLeft;
}
public function getColumns() { return 2; }
public function getRows() { return 7; }
public function getColumns()
{
return 2;
}
public function getRows()
{
return 7;
}
public function getLabelColumnSpacing() { return $this->columnSpacing; }
public function getLabelRowSpacing() { return $this->rowSpacing; }
public function getLabelColumnSpacing()
{
return $this->columnSpacing;
}
public function getLabelRowSpacing()
{
return $this->rowSpacing;
}
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelWidth()
{
return $this->labelWidth;
}
public function getLabelHeight()
{
return $this->labelHeight;
}
public function getLabelBorder() { return 0; }
public function getLabelBorder()
{
return 0;
}
}
?>

View File

@@ -14,23 +14,59 @@ class L7163_A extends L7163
private const FIELD_SIZE = 4.80;
private const FIELD_MARGIN = 0.30;
public function getUnit() { return 'mm'; }
public function getUnit()
{
return 'mm';
}
public function getLabelMarginTop() { return 1.0; }
public function getLabelMarginBottom() { return 1.0; }
public function getLabelMarginLeft() { return 1.0; }
public function getLabelMarginRight() { return 1.0; }
public function getLabelMarginTop()
{
return 1.0;
}
public function getLabelMarginBottom()
{
return 1.0;
}
public function getLabelMarginLeft()
{
return 1.0;
}
public function getLabelMarginRight()
{
return 1.0;
}
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 4; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 4;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
$usableWidth = $pa->w;

View File

@@ -31,7 +31,8 @@ abstract class _3490 extends RectangleSheet
private float $labelWidth;
private float $labelHeight;
public function __construct() {
public function __construct()
{
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 2);
$this->pageWidth = $paperSize->width;
$this->pageHeight = $paperSize->height;
@@ -48,24 +49,63 @@ abstract class _3490 extends RectangleSheet
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
}
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageWidth()
{
return $this->pageWidth;
}
public function getPageHeight()
{
return $this->pageHeight;
}
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginTop; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginLeft; }
public function getPageMarginTop()
{
return $this->pageMarginTop;
}
public function getPageMarginBottom()
{
return $this->pageMarginTop;
}
public function getPageMarginLeft()
{
return $this->pageMarginLeft;
}
public function getPageMarginRight()
{
return $this->pageMarginLeft;
}
public function getColumns() { return 3; }
public function getRows() { return 10; }
public function getColumns()
{
return 3;
}
public function getRows()
{
return 10;
}
public function getLabelColumnSpacing() { return $this->columnSpacing; }
public function getLabelRowSpacing() { return $this->rowSpacing; }
public function getLabelColumnSpacing()
{
return $this->columnSpacing;
}
public function getLabelRowSpacing()
{
return $this->rowSpacing;
}
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelWidth()
{
return $this->labelWidth;
}
public function getLabelHeight()
{
return $this->labelHeight;
}
public function getLabelBorder() { return 0; }
public function getLabelBorder()
{
return 0;
}
}
?>

View File

@@ -14,23 +14,59 @@ class _3490_A extends _3490
private const FIELD_SIZE = 0.150;
private const FIELD_MARGIN = 0.012;
public function getUnit() { return 'in'; }
public function getUnit()
{
return 'in';
}
public function getLabelMarginTop() { return 0.06; }
public function getLabelMarginBottom() { return 0.06; }
public function getLabelMarginLeft() { return 0.06; }
public function getLabelMarginRight() { return 0.06; }
public function getLabelMarginTop()
{
return 0.06;
}
public function getLabelMarginBottom()
{
return 0.06;
}
public function getLabelMarginLeft()
{
return 0.06;
}
public function getLabelMarginRight()
{
return 0.06;
}
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getSupportAssetTag()
{
return false;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 3;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
$currentX = $pa->x1;

View File

@@ -31,7 +31,8 @@ abstract class _5267 extends RectangleSheet
private float $labelWidth;
private float $labelHeight;
public function __construct() {
public function __construct()
{
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 2);
$this->pageWidth = $paperSize->width;
$this->pageHeight = $paperSize->height;
@@ -48,24 +49,63 @@ abstract class _5267 extends RectangleSheet
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
}
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageWidth()
{
return $this->pageWidth;
}
public function getPageHeight()
{
return $this->pageHeight;
}
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginTop; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginLeft; }
public function getPageMarginTop()
{
return $this->pageMarginTop;
}
public function getPageMarginBottom()
{
return $this->pageMarginTop;
}
public function getPageMarginLeft()
{
return $this->pageMarginLeft;
}
public function getPageMarginRight()
{
return $this->pageMarginLeft;
}
public function getColumns() { return 4; }
public function getRows() { return 20; }
public function getColumns()
{
return 4;
}
public function getRows()
{
return 20;
}
public function getLabelColumnSpacing() { return $this->columnSpacing; }
public function getLabelRowSpacing() { return $this->rowSpacing; }
public function getLabelColumnSpacing()
{
return $this->columnSpacing;
}
public function getLabelRowSpacing()
{
return $this->rowSpacing;
}
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelWidth()
{
return $this->labelWidth;
}
public function getLabelHeight()
{
return $this->labelHeight;
}
public function getLabelBorder() { return 0; }
public function getLabelBorder()
{
return 0;
}
}
?>

View File

@@ -12,23 +12,59 @@ class _5267_A extends _5267
private const FIELD_SIZE = 0.150;
private const FIELD_MARGIN = 0.012;
public function getUnit() { return 'in'; }
public function getUnit()
{
return 'in';
}
public function getLabelMarginTop() { return 0.02; }
public function getLabelMarginBottom() { return 0.00; }
public function getLabelMarginLeft() { return 0.04; }
public function getLabelMarginRight() { return 0.04; }
public function getLabelMarginTop()
{
return 0.02;
}
public function getLabelMarginBottom()
{
return 0.00;
}
public function getLabelMarginLeft()
{
return 0.04;
}
public function getLabelMarginRight()
{
return 0.04;
}
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return false; }
public function getSupportFields() { return 1; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getSupportAssetTag()
{
return false;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return false;
}
public function getSupportFields()
{
return 1;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
if ($record->has('barcode1d')) {

View File

@@ -31,7 +31,8 @@ abstract class _5520 extends RectangleSheet
private float $labelWidth;
private float $labelHeight;
public function __construct() {
public function __construct()
{
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 2);
$this->pageWidth = $paperSize->width;
$this->pageHeight = $paperSize->height;
@@ -48,24 +49,63 @@ abstract class _5520 extends RectangleSheet
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
}
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageWidth()
{
return $this->pageWidth;
}
public function getPageHeight()
{
return $this->pageHeight;
}
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginTop; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginLeft; }
public function getPageMarginTop()
{
return $this->pageMarginTop;
}
public function getPageMarginBottom()
{
return $this->pageMarginTop;
}
public function getPageMarginLeft()
{
return $this->pageMarginLeft;
}
public function getPageMarginRight()
{
return $this->pageMarginLeft;
}
public function getColumns() { return 3; }
public function getRows() { return 10; }
public function getColumns()
{
return 3;
}
public function getRows()
{
return 10;
}
public function getLabelColumnSpacing() { return $this->columnSpacing; }
public function getLabelRowSpacing() { return $this->rowSpacing; }
public function getLabelColumnSpacing()
{
return $this->columnSpacing;
}
public function getLabelRowSpacing()
{
return $this->rowSpacing;
}
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelWidth()
{
return $this->labelWidth;
}
public function getLabelHeight()
{
return $this->labelHeight;
}
public function getLabelBorder() { return 0; }
public function getLabelBorder()
{
return 0;
}
}
?>

View File

@@ -14,23 +14,59 @@ class _5520_A extends _5520
private const FIELD_SIZE = 0.150;
private const FIELD_MARGIN = 0.012;
public function getUnit() { return 'in'; }
public function getUnit()
{
return 'in';
}
public function getLabelMarginTop() { return 0.06; }
public function getLabelMarginBottom() { return 0.06; }
public function getLabelMarginLeft() { return 0.06; }
public function getLabelMarginRight() { return 0.06; }
public function getLabelMarginTop()
{
return 0.06;
}
public function getLabelMarginBottom()
{
return 0.06;
}
public function getLabelMarginLeft()
{
return 0.06;
}
public function getLabelMarginRight()
{
return 0.06;
}
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getSupportAssetTag()
{
return false;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 3;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
$currentX = $pa->x1;

View File

@@ -15,23 +15,59 @@ class _5520_B extends _5520
private const FIELD_SIZE = 0.150;
private const FIELD_MARGIN = 0.012;
public function getUnit() { return 'in'; }
public function getUnit()
{
return 'in';
}
public function getLabelMarginTop() { return 0.06; }
public function getLabelMarginBottom() { return 0.06; }
public function getLabelMarginLeft() { return 0.06; }
public function getLabelMarginRight() { return 0.06; }
public function getLabelMarginTop()
{
return 0.06;
}
public function getLabelMarginBottom()
{
return 0.06;
}
public function getLabelMarginLeft()
{
return 0.06;
}
public function getLabelMarginRight()
{
return 0.06;
}
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return false; }
public function getSupportFields() { return 2; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getSupportAssetTag()
{
return false;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return false;
}
public function getSupportFields()
{
return 2;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
$currentX = $pa->x1;

View File

@@ -11,9 +11,24 @@ abstract class TZe_12mm extends Label
private const MARGIN_SIDES = 3.20;
private const MARGIN_ENDS = 3.20;
public function getHeight() { return Helper::convertUnit(self::HEIGHT, 'mm', $this->getUnit()); }
public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); }
public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());}
public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getHeight()
{
return Helper::convertUnit(self::HEIGHT, 'mm', $this->getUnit());
}
public function getMarginTop()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginBottom()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginLeft()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
public function getMarginRight()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
}

View File

@@ -8,18 +8,45 @@ class TZe_12mm_A extends TZe_12mm
private const BARCODE_MARGIN = 0.30;
private const TEXT_SIZE_MOD = 1.00;
public function getUnit() { return 'mm'; }
public function getWidth() { return 50.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return false; }
public function getSupportFields() { return 1; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return false; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 50.0;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return false;
}
public function getSupportFields()
{
return 1;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return false;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
if ($record->has('barcode1d')) {

View File

@@ -11,9 +11,24 @@ abstract class TZe_18mm extends Label
private const MARGIN_SIDES = 3.20;
private const MARGIN_ENDS = 3.20;
public function getHeight() { return Helper::convertUnit(self::HEIGHT, 'mm', $this->getUnit()); }
public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); }
public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());}
public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getHeight()
{
return Helper::convertUnit(self::HEIGHT, 'mm', $this->getUnit());
}
public function getMarginTop()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginBottom()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginLeft()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
public function getMarginRight()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
}

View File

@@ -8,18 +8,45 @@ class TZe_18mm_A extends TZe_18mm
private const BARCODE_MARGIN = 0.30;
private const TEXT_SIZE_MOD = 1.00;
public function getUnit() { return 'mm'; }
public function getWidth() { return 50.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return false; }
public function getSupportFields() { return 1; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return false; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 50.0;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return false;
}
public function getSupportFields()
{
return 1;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return false;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
if ($record->has('barcode1d')) {

View File

@@ -11,9 +11,24 @@ abstract class TZe_24mm extends Label
private const MARGIN_SIDES = 3.20;
private const MARGIN_ENDS = 3.20;
public function getHeight() { return Helper::convertUnit(self::HEIGHT, 'mm', $this->getUnit()); }
public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); }
public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());}
public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getHeight()
{
return Helper::convertUnit(self::HEIGHT, 'mm', $this->getUnit());
}
public function getMarginTop()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginBottom()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginLeft()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
public function getMarginRight()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
}

View File

@@ -13,18 +13,45 @@ class TZe_24mm_A extends TZe_24mm
private const FIELD_SIZE = 3.20;
private const FIELD_MARGIN = 0.15;
public function getUnit() { return 'mm'; }
public function getWidth() { return 65.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 65.0;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 3;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -15,18 +15,45 @@ class TZe_24mm_B extends TZe_24mm
private const FIELD_SIZE = 3.20;
private const FIELD_MARGIN = 0.15;
public function getUnit() { return 'mm'; }
public function getWidth() { return 73.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return true; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 73.0;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 3;
}
public function getSupportLogo()
{
return true;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -15,18 +15,45 @@ class TZe_24mm_C extends TZe_24mm
private const FIELD_SIZE = 3.20;
private const FIELD_MARGIN = 0.15;
public function getUnit() { return 'mm'; }
public function getWidth() { return 34.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 0; }
public function getSupportLogo() { return true; }
public function getSupportTitle() { return false; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 34.0;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 0;
}
public function getSupportLogo()
{
return true;
}
public function getSupportTitle()
{
return false;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -14,18 +14,45 @@ class TZe_24mm_D extends TZe_24mm
private const FIELD_MARGIN = 0.35;
private const BARCODE1D_SIZE = 3.00; // Size for the C128 barcode at bottom
public function getUnit() { return 'mm'; }
public function getWidth() { return 65.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 65.0;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 3;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -14,10 +14,28 @@ abstract class TZe_62mm_Landscape extends Label
private const MARGIN_SIDES = 1.50;
private const MARGIN_ENDS = 1.50;
public function getWidth() { return Helper::convertUnit(self::WIDTH, 'mm', $this->getUnit()); }
public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); }
public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());}
public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
public function getRotation() { return 90; }
public function getWidth()
{
return Helper::convertUnit(self::WIDTH, 'mm', $this->getUnit());
}
public function getMarginTop()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginBottom()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());
}
public function getMarginLeft()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
public function getMarginRight()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit());
}
public function getRotation()
{
return 90;
}
}

View File

@@ -4,14 +4,38 @@ namespace App\Models\Labels\Tapes\Brother;
class TZe_62mm_Landscape_A extends TZe_62mm_Landscape
{
public function getUnit() { return 'mm'; }
public function getHeight() { return 31.50; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 2; }
public function getSupportLogo() { return true; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getHeight()
{
return 31.50;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 2;
}
public function getSupportLogo()
{
return true;
}
public function getSupportTitle()
{
return true;
}
private const BARCODE1D_HEIGHT = 3.00;
private const BARCODE1D_MARGIN = 3.00;
@@ -27,9 +51,12 @@ class TZe_62mm_Landscape_A extends TZe_62mm_Landscape
private const FIELD_SIZE = 3.00;
private const FIELD_MARGIN = 0.10;
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -11,9 +11,24 @@ abstract class LabelWriter extends Label
private const MARGIN_SIDES = 0.1;
private const MARGIN_ENDS = 0.1;
public function getHeight() { return Helper::convertUnit(self::HEIGHT, 'in', $this->getUnit()); }
public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'in', $this->getUnit()); }
public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'in', $this->getUnit());}
public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'in', $this->getUnit()); }
public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'in', $this->getUnit()); }
public function getHeight()
{
return Helper::convertUnit(self::HEIGHT, 'in', $this->getUnit());
}
public function getMarginTop()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'in', $this->getUnit());
}
public function getMarginBottom()
{
return Helper::convertUnit(self::MARGIN_SIDES, 'in', $this->getUnit());
}
public function getMarginLeft()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'in', $this->getUnit());
}
public function getMarginRight()
{
return Helper::convertUnit(self::MARGIN_ENDS, 'in', $this->getUnit());
}
}

View File

@@ -14,19 +14,49 @@ class LabelWriter_1933081 extends LabelWriter
private const FIELD_SIZE = 2.80;
private const FIELD_MARGIN = 0.15;
public function getUnit() { return 'mm'; }
public function getWidth() { return 89; }
public function getHeight() { return 25; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 5; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 89;
}
public function getHeight()
{
return 25;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 5;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -14,19 +14,49 @@ class LabelWriter_2112283 extends LabelWriter
private const FIELD_SIZE = 2.80;
private const FIELD_MARGIN = 0.15;
public function getUnit() { return 'mm'; }
public function getWidth() { return 54; }
public function getHeight() { return 25; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 5; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 54;
}
public function getHeight()
{
return 25;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 5;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -16,18 +16,45 @@ class LabelWriter_30252 extends LabelWriter
public function getUnit() { return 'mm'; }
public function getWidth() { return 96.52; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getWidth()
{
return 96.52;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 3;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {}
public function preparePDF($pdf)
{
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -15,28 +15,30 @@ abstract class Continuous_53mm extends GenericTape
*
* Assumes tape is continuous, set to false and specify
* $spacing in concrete classfor die-cut labels
*
*
* @param float $height Height of the label in mm (default 60mm)
* @param bool $continuous Whether the tape is continuous or pre-cut
* @param float $spacing Spacing between labels for non-continuous tapes (in mm)
* @param float $height Height of the label in mm (default 60mm)
* @param bool $continuous Whether the tape is continuous or pre-cut
* @param float $spacing Spacing between labels for non-continuous tapes (in mm)
*/
public function __construct($height = 60.0, $continuous = true, $spacing = 0.0) {
public function __construct($height = 60.0, $continuous = true, $spacing = 0.0)
{
parent::__construct(self::TAPE_WIDTH, $height, $continuous, $spacing);
$this->tapeHeight = $height;
}
public function getBarcodeRatio() {
public function getBarcodeRatio()
{
return 0.9; // Barcode should use 90% of available width
}
/**
* Calculate the required height for the content
*
* @param $record The record to calculate height for
* @param $record The record to calculate height for
* @return float The calculated height in mm
*/
protected function calculateRequiredHeight($record) {
protected function calculateRequiredHeight($record)
{
$height = $this->marginTop + $this->marginBottom;
// Add title height if present
@@ -45,8 +47,9 @@ abstract class Continuous_53mm extends GenericTape
}
// Add barcode height if present
if (($record->has('barcode2d') && $this->getSupport2DBarcode()) ||
($record->has('barcode') && $this->getSupport1DBarcode())) {
if (($record->has('barcode2d') && $this->getSupport2DBarcode())
|| ($record->has('barcode') && $this->getSupport1DBarcode())
) {
$pa = $this->getPrintableArea();
$usableWidth = $pa->w;
$barcodeSize = $usableWidth * $this->getBarcodeRatio();
@@ -71,31 +74,34 @@ abstract class Continuous_53mm extends GenericTape
/**
* Override the writeAll method to support dynamic page sizes for continuous tapes
*/
public function writeAll($pdf, $data) {
public function writeAll($pdf, $data)
{
// Use auto-sizing for continuous tapes, fixed height for die-cut tapes
if ($this->continuous) {
$data->each(function ($record, $index) use ($pdf) {
// Calculate the required height for this record
$requiredHeight = $this->calculateRequiredHeight($record);
$data->each(
function ($record, $index) use ($pdf) {
// Calculate the required height for this record
$requiredHeight = $this->calculateRequiredHeight($record);
// Temporarily update the height property
$originalHeight = $this->height;
$this->height = $requiredHeight;
// Temporarily update the height property
$originalHeight = $this->height;
$this->height = $requiredHeight;
// Add a new page with the calculated dimensions
$pdf->AddPage(
$this->getOrientation(),
[$this->getWidth(), $requiredHeight],
false, // Don't reset page number
false // Don't reset object ID
);
// Add a new page with the calculated dimensions
$pdf->AddPage(
$this->getOrientation(),
[$this->getWidth(), $requiredHeight],
false, // Don't reset page number
false // Don't reset object ID
);
// Write the content
$this->write($pdf, $record);
// Write the content
$this->write($pdf, $record);
// Restore the original height
$this->height = $originalHeight;
});
// Restore the original height
$this->height = $originalHeight;
}
);
} else {
// Use the default implementation for non-continuous (die-cut) tapes
parent::writeAll($pdf, $data);

View File

@@ -5,19 +5,42 @@ namespace App\Models\Labels\Tapes\Generic;
class Continuous_53mm_A extends Continuous_53mm
{
public function getUnit() { return 'mm'; }
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 5; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function getUnit()
{
return 'mm';
}
public function getSupportAssetTag()
{
return false;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 5;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf) {
public function preparePDF($pdf)
{
$pdf->SetAutoPageBreak(false);
}
public function write($pdf, $record) {
public function write($pdf, $record)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -13,11 +13,12 @@ abstract class Continuous_Landscape_0_59in extends GenericTape
protected float $minHeight = 1;
/**
* @param float $length Length of the label in inches (default 2.36in which is 60mm)
* @param bool $continuous Whether the tape is continuous or pre-cut
* @param float $spacing Spacing between labels for non-continuous tapes (in inches)
* @param float $length Length of the label in inches (default 2.36in which is 60mm)
* @param bool $continuous Whether the tape is continuous or pre-cut
* @param float $spacing Spacing between labels for non-continuous tapes (in inches)
*/
public function __construct($length = 0.6, $continuous = true, $spacing = 0.0) {
public function __construct($length = 0.6, $continuous = true, $spacing = 0.0)
{
// Swap width and height for landscape orientation
// The height becomes the width, and the length becomes the height
parent::__construct($length, self::TAPE_WIDTH, $continuous, $spacing);
@@ -44,24 +45,27 @@ abstract class Continuous_Landscape_0_59in extends GenericTape
$this->tagSize = $baseFontSize * 0.8; // 80% of base font size
}
public function getBarcodeRatio() {
public function getBarcodeRatio()
{
return 1.0; // Barcode should use 100% of available height
}
/**
* Calculate the required length for the content
*
* @param $record The record to calculate length for
* @param $record The record to calculate length for
* @return float The calculated length in inches
*/
protected function calculateRequiredLength($record) {
protected function calculateRequiredLength($record)
{
// Calculate length needed for barcode and fields side by side
$requiredLength = 0;
// Add barcode length if present
if (($record->has('barcode2d') && $this->getSupport2DBarcode()) ||
($record->has('barcode') && $this->getSupport1DBarcode())) {
if (($record->has('barcode2d') && $this->getSupport2DBarcode())
|| ($record->has('barcode') && $this->getSupport1DBarcode())
) {
// Use full tape width for barcode size
$barcodeSize = self::TAPE_WIDTH;
$requiredLength += $barcodeSize + $this->barcodeMargin * 0.3; // Minimal margin
@@ -107,14 +111,15 @@ abstract class Continuous_Landscape_0_59in extends GenericTape
/**
* Calculate text width accurately using the PDF object
*
* @param $pdf The PDF object
* @param string $text The text to measure
* @param string $font The font to use
* @param string $style The font style
* @param float $size The font size
* @param $pdf The PDF object
* @param string $text The text to measure
* @param string $font The font to use
* @param string $style The font style
* @param float $size The font size
* @return float The calculated width
*/
protected function calculateTextWidth($pdf, $text, $font, $style, $size) {
protected function calculateTextWidth($pdf, $text, $font, $style, $size)
{
$originalFont = $pdf->getFontFamily();
$originalStyle = $pdf->getFontStyle();
$originalSize = $pdf->getFontSizePt();
@@ -131,37 +136,40 @@ abstract class Continuous_Landscape_0_59in extends GenericTape
/**
* Override the writeAll method to support dynamic page sizes for continuous tapes
*/
public function writeAll($pdf, $data) {
public function writeAll($pdf, $data)
{
// Use auto-sizing for continuous tapes, fixed height for die-cut tapes
if ($this->continuous) {
$data->each(function ($record, $index) use ($pdf) {
// Calculate the required length by calling write with calculateOnly=true
$requiredLength = $this->write($pdf, $record);
$data->each(
function ($record, $index) use ($pdf) {
// Calculate the required length by calling write with calculateOnly=true
$requiredLength = $this->write($pdf, $record);
// If write didn't return a length (old implementation), fall back to calculateRequiredLength
if ($requiredLength === null) {
$requiredLength = $this->calculateRequiredLength($record);
// If write didn't return a length (old implementation), fall back to calculateRequiredLength
if ($requiredLength === null) {
$requiredLength = $this->calculateRequiredLength($record);
}
// Temporarily update the height property
$originalHeight = $this->height;
$this->height = self::TAPE_WIDTH; // Keep height fixed at tape width
// Add a new page with the calculated dimensions
// Keep height fixed at TAPE_WIDTH, use calculated length for width
$pdf->AddPage(
$this->getOrientation(),
[$requiredLength, self::TAPE_WIDTH],
false, // Don't reset page number
false // Don't reset object ID
);
// Write the content
$this->write($pdf, $record);
// Restore the original height
$this->height = $originalHeight;
}
// Temporarily update the height property
$originalHeight = $this->height;
$this->height = self::TAPE_WIDTH; // Keep height fixed at tape width
// Add a new page with the calculated dimensions
// Keep height fixed at TAPE_WIDTH, use calculated length for width
$pdf->AddPage(
$this->getOrientation(),
[$requiredLength, self::TAPE_WIDTH],
false, // Don't reset page number
false // Don't reset object ID
);
// Write the content
$this->write($pdf, $record);
// Restore the original height
$this->height = $originalHeight;
});
);
} else {
// Use the default implementation for non-continuous (die-cut) tapes
parent::writeAll($pdf, $data);

View File

@@ -4,19 +4,42 @@ namespace App\Models\Labels\Tapes\Generic;
class Continuous_Landscape_0_59in_A extends Continuous_Landscape_0_59in
{
public function getUnit() { return 'in'; }
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 2; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return false; }
public function getUnit()
{
return 'in';
}
public function getSupportAssetTag()
{
return false;
}
public function getSupport1DBarcode()
{
return true;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 2;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return false;
}
public function preparePDF($pdf) {
public function preparePDF($pdf)
{
$pdf->SetAutoPageBreak(false);
}
public function write($pdf, $record, $calculateOnly = false) {
public function write($pdf, $record, $calculateOnly = false)
{
$pa = $this->getPrintableArea();
$currentX = $pa->x1;

View File

@@ -35,12 +35,13 @@ abstract class GenericTape extends Label
/**
* Constructor for generic tape
*
* @param float $width Width of the tape in mm
* @param float $height Height of the label in mm (for continuous tapes, this is the default height)
* @param bool $continuous Whether the tape is continuous or pre-cut
* @param float $spacing Spacing between labels for non-continuous tapes (in mm)
* @param float $width Width of the tape in mm
* @param float $height Height of the label in mm (for continuous tapes, this is the default height)
* @param bool $continuous Whether the tape is continuous or pre-cut
* @param float $spacing Spacing between labels for non-continuous tapes (in mm)
*/
public function __construct(float $width, float $height, bool $continuous = true, float $spacing = 0.0) {
public function __construct(float $width, float $height, bool $continuous = true, float $spacing = 0.0)
{
$this->width = $width;
$this->height = $height;
$this->continuous = $continuous;
@@ -70,17 +71,38 @@ abstract class GenericTape extends Label
}
// Unit of measurement
public function getUnit() { return 'mm'; }
public function getUnit()
{
return 'mm';
}
// Label dimensions
public function getWidth() { return $this->width; }
public function getHeight() { return $this->height; }
public function getWidth()
{
return $this->width;
}
public function getHeight()
{
return $this->height;
}
// Margins
public function getMarginTop() { return $this->marginTop; }
public function getMarginBottom() { return $this->marginBottom; }
public function getMarginLeft() { return $this->marginLeft; }
public function getMarginRight() { return $this->marginRight; }
public function getMarginTop()
{
return $this->marginTop;
}
public function getMarginBottom()
{
return $this->marginBottom;
}
public function getMarginLeft()
{
return $this->marginLeft;
}
public function getMarginRight()
{
return $this->marginRight;
}
/**
@@ -88,7 +110,8 @@ abstract class GenericTape extends Label
*
* @return bool
*/
public function isContinuous() {
public function isContinuous()
{
return $this->continuous;
}
@@ -97,7 +120,8 @@ abstract class GenericTape extends Label
*
* @return float
*/
public function getSpacing() {
public function getSpacing()
{
return $this->spacing;
}
}

Some files were not shown because too many files have changed in this diff Show More