Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6c77661
Merge pull request #1 from Part-DB/master
d-buchmann Nov 10, 2023
47e7082
Merge branch 'Part-DB:master' into master
d-buchmann Nov 15, 2023
62d2790
Merge branch 'Part-DB:master' into master
d-buchmann Nov 16, 2023
d623224
Merge branch 'Part-DB:master' into master
d-buchmann Jan 31, 2024
4292894
Merge branch 'Part-DB:master' into master
d-buchmann Feb 26, 2024
ec361a1
Merge branch 'Part-DB:master' into master
d-buchmann Jan 3, 2025
463799c
Create update.sh
d-buchmann Jan 3, 2025
0ea39b9
Merge branch 'Part-DB:master' into master
d-buchmann Jan 16, 2025
f0a3329
Merge branch 'Part-DB:master' into master
d-buchmann May 21, 2025
6b4ff26
More generous search
d-buchmann May 28, 2025
8952116
Create update.sh
d-buchmann Jan 3, 2025
07e064a
Merge branch 'master' of https://github.com/d-buchmann/Part-DB-server
d-buchmann Jun 27, 2025
a8a7234
Merge remote-tracking branch 'upstream/master'
d-buchmann Aug 13, 2025
1db857e
Merge remote-tracking branch 'upstream/master'
d-buchmann Aug 14, 2025
824024f
Merge remote-tracking branch 'upstream/master'
d-buchmann Sep 2, 2025
4c713d2
Merge remote-tracking branch 'upstream/master'
d-buchmann Sep 10, 2025
311336e
Merge remote-tracking branch 'remotes/upstream/master'
d-buchmann Oct 7, 2025
3b69151
Merge branch 'master' into tweak-search
d-buchmann Oct 28, 2025
bc226f0
Update tests.yml
d-buchmann Nov 7, 2025
ea984d1
Merge branch 'master' of https://github.com/d-buchmann/Part-DB-server
d-buchmann Nov 11, 2025
91a9c4e
Merge branch 'master' of https://github.com/d-buchmann/Part-DB-server…
d-buchmann Dec 16, 2025
cc902a7
Merge branch 'master' into tweak-search
d-buchmann Feb 12, 2026
662a314
Merge branch 'tweak-search' of https://github.com/d-buchmann/Part-DB-…
d-buchmann Feb 16, 2026
0d80ac0
Merge branch 'master' into tweak-search
d-buchmann Feb 16, 2026
1d6b634
Update PartSearchFilter.php
d-buchmann Feb 16, 2026
449b944
Update PartSearchFilter.php
d-buchmann Feb 16, 2026
d903c1c
Update PartSearchFilter.php
d-buchmann Feb 16, 2026
e5b3507
Update PartSearchFilter.php
d-buchmann Feb 16, 2026
a131d1c
Update PartSearchFilter.php
d-buchmann Feb 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ jobs:
with:
env_vars: PHP_VERSION,DB_TYPE
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
fail_ci_if_error: false

- name: Test app:clean-attachments
run: php bin/console partdb:attachments:clean-unused -n
Expand Down
70 changes: 47 additions & 23 deletions src/DataTables/Filters/PartSearchFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,16 @@ class PartSearchFilter implements FilterInterface
/** @var bool Use Internal Part number for searching */
protected bool $ipn = true;

/** @var int Helper variable for hacky array_map variable injection */
protected int $it = 0;

public function __construct(
/** @var string The string to query for */
protected string $keyword
)
{
// Transform keyword and trim excess spaces
$keyword = trim(str_replace('+', ' ', $keyword));
}

protected function getFieldsToSearch(): array
Expand Down Expand Up @@ -133,36 +138,56 @@ public function apply(QueryBuilder $queryBuilder): void
if (($fields_to_search === [] && !$search_dbId) || $this->keyword === '') {
return;
}

$expressions = [];
$params = [];

if($fields_to_search !== []) {
//Convert the fields to search to a list of expressions
$expressions = array_map(function (string $field): string {
if ($this->regex) {
return sprintf("REGEXP(%s, :search_query) = TRUE", $field);
}

return sprintf("ILIKE(%s, :search_query) = TRUE", $field);
}, $fields_to_search);

//For regex, we pass the query as is, for like we add % to the start and end as wildcards
if ($this->regex) {
$queryBuilder->setParameter('search_query', $this->keyword);
} else {
//Escape % and _ characters in the keyword
$this->keyword = str_replace(['%', '_'], ['\%', '\_'], $this->keyword);
$queryBuilder->setParameter('search_query', '%' . $this->keyword . '%');
}
}

//Use equal expression to just search for exact numeric matches
if ($search_dbId) {
$expressions[] = $queryBuilder->expr()->eq('part.id', ':id_exact');
$queryBuilder->setParameter('id_exact', (int) $this->keyword,
$params[] = new \Doctrine\ORM\Query\Parameter('id_exact', (int) $this->keyword,
ParameterType::INTEGER);
}

if ($this->regex) {
//Convert the fields to search to a list of expressions
$expressions = array_map(function (string $field): string {
return sprintf("REGEXP(%s, :search_query) = TRUE", $field);
}, $fields_to_search);

//For regex, we pass the query as is, save html special chars
$params[] = new \Doctrine\ORM\Query\Parameter('search_query', $this->keyword);
} else {
//Escape % and _ characters in the keyword
$this->keyword = str_replace(['%', '_'], ['\%', '\_'], $this->keyword);

//Split keyword on spaces, but limit token count
$tokens = explode(' ', $this->keyword, 5);

//Perform search of every single token in every selected field
//AND-combine the results (all tokens must be present in any of the results)
for ($i = 0; $i < sizeof($tokens); $i++) {
$this->it = $i;
$tokens[$i] = trim($tokens[$i]);

//Skip empty words (e.g. because of multiple spaces)
if ($tokens[$i] === '') {
continue;
}
//Convert the fields to search to a list of expressions
$expressions = array_map(function (string $field): string {
return sprintf("ILIKE(%s, :search_query%u) = TRUE", $field, $this->it);
}, $fields_to_search);

//Aggregate the parameters for consolidated commission
$params[] = new \Doctrine\ORM\Query\Parameter('search_query' . $i,
'%' . $tokens[$i] . '%');
}
}

$queryBuilder->setParameters(
new \Doctrine\Common\Collections\ArrayCollection($params)
);
//Guard condition
if (!empty($expressions)) {
//Add Or concatenation of the expressions to our query
Expand Down Expand Up @@ -337,5 +362,4 @@ public function setComment(bool $comment): PartSearchFilter
return $this;
}


}
164 changes: 164 additions & 0 deletions update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
##!/bin/bash
set -euo pipefail

### constants ###
FILE="Part-DB-release-stage"
GITREPO="/opt/partdb/git-repo"
PRODENV="/var/www/Part-DB-server"
BACKUPDIR="/HDD5/backups/partdb"
WEB_AVAILABLE="/etc/apache2/sites-available"
WEB_ENABLED="/etc/apache2/sites-enabled"
WEBSERVICE="apache2"
LIVE_CONF="01_partdb.conf"
TEST_CONF="06_partdb_testing.conf"
MNT_CONF="07_partdb_maintenance.conf"

# We should probably do a sanity check here?
DBUSER="$1"
DBPASSWD="$2"

### variables ###
stage="1"

echo ""
echo "*** Part-DB upgrade tool v0.0001 (WorksForMe* edition) ***"


if [ $(whoami) != 'root' ]; then
echo ""
echo "This script must be run as root!"
exit -1
fi

if [ -f $FILE ]; then
stage=$(<$FILE)
fi

if [ "$stage" = "1" ]; then # no update currently in progress
cd $GITREPO
git fetch --tags
# get latest version
gitver=$(git describe --tags --abbrev=0)
currentver=$(</var/www/Part-DB-server/VERSION)
if [ "$gitver" = "v$currentver" ]; then
echo "* Already up-to-date!"
exit 0
fi
echo "New version $gitver avaliable (currently on $currentver)."
fi

for curstage in $(seq $(($stage)) 4)
do
echo ""
echo "* Stage $curstage: continue? (y/n)"
read -r response
echo ""
if [ "$response" = "y" ]; then
case $curstage in
"1")
if [ "$stage" = "1" ]; then
echo "* Stage 1: Put Part-DB in maintenance mode"
# remove link to current PartDB VHost
rm -f $WEB_ENABLED/$LIVE_CONF
# put up a maintenance notice on the URL
ln -sf $WEB_AVAILABLE/$MNT_CONF $WEB_ENABLED/$LIVE_CONF
# put up extra url for testing new part-db (not necessary, may always exist)
# ln -sf $WEB_AVAILABLE/partdb_testing.conf $WEB_ENABLED/partdb_testing.conf
# reload apache
if ! [ `systemctl reload $WEBSERVICE && systemctl is-active --quiet $WEBSERVICE` ]; then
echo "* Webserver restart failed! Please check your $WEBSERVICE site configurations."
break
fi
echo "* Part-DB now in maintenance mode, update may proceed."
echo "2" > $FILE
else
echo "* Invalid stage: $stage, expected 1"
exit 1
fi
;;
"2")
if [ "$stage" = "2" ]; then
echo "* Stage 2: Dump DB and update Part-DB via git"
# cd into working dir
cd $GITREPO
git fetch --tags
# get latest version
version=$(git describe --tags --abbrev=0)
# dump DB, preventing overwrite by re-execution if e.g. the migration broke the database structure
mysqldump -u$DBUSER -p$DBPASSWD partdb > $BACKUPDIR/partdb_before_update_$version_$(date -Iseconds).sql
# pull changes, checkout latest tag
git pull && git checkout $version
# copy config and media files and correct ownership
cp "$PRODENV/.env.local" $GITREPO
cp -rn $PRODENV/public/media/ $GITREPO/public/
chown -R www-data:www-data $GITREPO
# merge .env with .env.local, config/services.yaml, config/parameters.yaml if changed
# TODO how to handle customizations ??? meld ???
echo "* Files are in place, build step pending"
echo "3" > $FILE
else
echo "* Invalid stage: $stage, expected 2"
exit 2
fi
;;
"3")
if [ "$stage" = "3" ] ; then
echo "* Stage 3: Build process"
# build steps
cd $GITREPO
environment=$(sed -nr 's/APP_ENV=(.*)/\1/p' .env.local)
if [ environment != "dev" ]; then
environment="no-dev"
fi
sudo -u www-data composer install --$environment -o
yarn install
yarn build
# check if installation succeeded and migrate db
sudo -u www-data php bin/console partdb:check-requirements
sudo -u www-data php bin/console doctrine:migrations:migrate
sudo -u www-data php bin/console cache:clear
# we can mess with the production db because we have a very recent backup
rsync -av --exclude=$GITREPO/.git* $GITREPO/ $PRODENV-test

echo "* The new Part-DB version can now be tested. You may need to merge .env.local with .env and check yaml files in config/."
echo "4" > $FILE
else
echo "* Invalid stage: $stage, expected 3"
exit 3
fi
;;
"4")
if [ "$stage" = "4" ]; then
echo "Stage 4: Put Part-DB back in production mode, retaining the old copy"
# copy all to prod environment
mv $PRODENV $PRODENV-old
mv $PRODENV-test $PRODENV
# remove link to maintenance PartDB VHost
rm $WEB_ENABLED/$LIVE_CONF $WEB_ENABLED/$TEST_CONF
# link the new partdb version
ln -sf $WEB_AVAILABLE/$LIVE_CONF $WEB_ENABLED/$LIVE_CONF
# reload apache
if ! [ `systemctl reload $WEBSERVICE && systemctl is-active --quiet $WEBSERVICE` ]; then
echo "* Webserver restart failed! Please check your $WEBSERVICE site configurations."
break
fi
echo ""
echo "*** Done. ***"
rm $FILE
else
echo "* Invalid stage: $stage, expected 4"
exit 4
fi
;;
esac
if [ -f $FILE ]; then
stage=$(<$FILE)
else
stage="1"
fi
else
echo "Update process aborted before stage $curstage."
break
fi
done
exit 0
Loading