Diff -- /var/www/vhosts/3dshawn.com/shop.3dshawn.com/admin_categories.cgi

O Operator
Diff

/var/www/vhosts/3dshawn.com/shop.3dshawn.com/admin_categories.cgi

added on local at 2026-07-01 22:09:16

Added
+167
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 4f6df3b2c924
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1#!/usr/bin/perl
2#======================================================================
3# ShopCart -- Admin default-categories editor.
4#
5# Manages the platform-wide DEFAULT category list. Every new seller
6# receives a one-time copy of this list into their own seller_categories
7# at first login (or first upload.cgi / categories.cgi visit, whichever
8# they hit first). Edits here only affect future seedings -- existing
9# sellers keep whatever they have.
10#
11# Mirrors /categories.cgi but operates on default_categories instead
12# of seller_categories. Reuses shopcart_categories.html via the
13# $form_action / $page_* tvars.
14#======================================================================
15use strict;
16use warnings;
17
18use lib '/var/www/vhosts/3dshawn.com/shop.3dshawn.com';
19use CGI;
20use MODS::Template;
21use MODS::DBConnect;
22use MODS::Login;
23use MODS::ShopCart::Config;
24use MODS::ShopCart::Wrapper;
25use MODS::ShopCart::Admin;
26use MODS::ShopCart::Categories;
27
28$| = 1;
29
30my $q = CGI->new;
31my $form = $q->Vars;
32my $auth = MODS::Login->new;
33my $tfile = MODS::Template->new;
34my $db = MODS::DBConnect->new;
35my $cfg = MODS::ShopCart::Config->new;
36my $wrap = MODS::ShopCart::Wrapper->new;
37my $admin = MODS::ShopCart::Admin->new;
38my $cat = MODS::ShopCart::Categories->new;
39my $DB = $cfg->settings('database_name');
40
41my $userinfo = $auth->login_verify();
42unless ($userinfo) {
43 print "Status: 302 Found\nLocation: /login.cgi?return=/admin_categories.cgi\n\n"; exit;
44}
45$admin->require_admin($userinfo);
46
47my $dbh = $db->db_connect();
48
49# Schema probe -- default_categories may not exist on a freshly-pulled
50# environment until the migration runs. Show a friendly nudge instead
51# of a 500 (see feedback_guard_optional_tables).
52unless ($cat->defaults_ready($db, $dbh, $DB)) {
53 $db->db_disconnect($dbh);
54 print "Content-Type: text/html; charset=utf-8\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\nExpires: 0\n\n";
55 $wrap->render({
56 userinfo => $userinfo,
57 page_key => 'admin_categories',
58 title => 'Default Categories',
59 body => qq~<div class="module"><div class="module-body" style="padding:40px;text-align:center">
60 <h1 style="font-family:var(--font-display);color:#fff">Default categories not installed yet</h1>
61 <p style="color:var(--col-text-2);margin-top:12px">Run the default_categories migration from <code>installation_instructions.html</code>, then refresh.</p>
62 </div></div>~,
63 });
64 exit;
65}
66
67# Flash from POST redirects.
68my $flash_msg = '';
69my $flash_kind = '';
70if (defined $form->{ok}) { $flash_msg = 'Saved.'; $flash_kind = 'ok'; }
71elsif (defined $form->{deleted}) { $flash_msg = 'Category deleted.'; $flash_kind = 'ok'; }
72elsif (defined $form->{dup}) { $flash_msg = 'A category with that name already exists.'; $flash_kind = 'danger'; }
73elsif (defined $form->{empty}) { $flash_msg = 'Name is required.'; $flash_kind = 'danger'; }
74
75# ---- POST handler ----------------------------------------------------
76if (($ENV{REQUEST_METHOD} || '') eq 'POST') {
77 my $act = lc($form->{_act} || ''); $act =~ s/[^a-z_]//g;
78 if ($act eq 'create') {
79 my $name = $form->{name} || '';
80 $name =~ s/^\s+|\s+$//g;
81 if (!length $name) {
82 $db->db_disconnect($dbh);
83 print "Status: 302 Found\nLocation: /admin_categories.cgi?empty=1\n\n"; exit;
84 }
85 my $id = $cat->default_create($db, $dbh, $DB,
86 name => $name,
87 description => $form->{description} || '',
88 color => $form->{color} || '',
89 icon => $form->{icon} || '',
90 sort_order => $form->{sort_order} || 0,
91 is_public => exists $form->{is_public} ? 1 : 1,
92 );
93 $db->db_disconnect($dbh);
94 my $q = $id ? 'ok=1' : 'dup=1';
95 print "Status: 302 Found\nLocation: /admin_categories.cgi?$q\n\n"; exit;
96 }
97 if ($act eq 'update') {
98 my $id = $form->{id}; $id =~ s/[^0-9]//g;
99 $cat->default_update($db, $dbh, $DB, $id,
100 name => $form->{name},
101 description => $form->{description},
102 color => $form->{color},
103 icon => $form->{icon},
104 sort_order => $form->{sort_order},
105 is_public => exists $form->{is_public} ? 1 : 0,
106 );
107 $db->db_disconnect($dbh);
108 print "Status: 302 Found\nLocation: /admin_categories.cgi?ok=1\n\n"; exit;
109 }
110 if ($act eq 'delete') {
111 my $id = $form->{id}; $id =~ s/[^0-9]//g;
112 $cat->default_delete($db, $dbh, $DB, $id);
113 $db->db_disconnect($dbh);
114 print "Status: 302 Found\nLocation: /admin_categories.cgi?deleted=1\n\n"; exit;
115 }
116 $db->db_disconnect($dbh);
117 print "Status: 302 Found\nLocation: /admin_categories.cgi\n\n"; exit;
118}
119
120# ---- GET: render the list -------------------------------------------
121my $cats = $cat->default_list($db, $dbh, $DB);
122
123my @rows;
124foreach my $c (@$cats) {
125 push @rows, {
126 id => $c->{id},
127 slug => _h($c->{slug}),
128 name => _h($c->{name}),
129 description => _h($c->{description} || ''),
130 color => _h($c->{color} || '#a78bfa'),
131 icon => _h($c->{icon} || ''),
132 model_count => 0, # not meaningful for defaults
133 is_public => $c->{is_public} ? 1 : 0,
134 sort_order => $c->{sort_order} || 0,
135 };
136}
137
138$db->db_disconnect($dbh);
139
140my $tvars = {
141 has_cats => scalar(@rows) ? 1 : 0,
142 cats => \@rows,
143 flash_msg => $flash_msg,
144 flash_kind => $flash_kind,
145 has_flash => length $flash_msg ? 1 : 0,
146 page_eyebrow => 'Admin &middot; Defaults',
147 page_title => 'Default Categories',
148 page_subtitle => 'The starter pack new sellers receive a copy of when they sign up. Edits here affect new sellers only -- existing sellers keep whatever they already have.',
149 form_action => '/admin_categories.cgi',
150};
151
152print "Content-Type: text/html; charset=utf-8\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\nExpires: 0\n\n";
153my $body = join('', $tfile->template('shopcart_categories.html', $tvars, $userinfo));
154$wrap->render({
155 userinfo => $userinfo,
156 page_key => 'admin_categories',
157 title => 'Default Categories',
158 body => $body,
159});
160exit;
161
162sub _h {
163 my $s = shift // '';
164 $s =~ s/&/&amp;/g; $s =~ s/</&lt;/g; $s =~ s/>/&gt;/g;
165 $s =~ s/"/&quot;/g; $s =~ s/'/&#39;/g;
166 return $s;
167}