2024-01-30 */ require_once(__DIR__.'/ui.php'); use Propel\Runtime\ActiveQuery\Criteria; use Symfony\Contracts\Cache\ItemInterface; use Propel\BOH\ArtistQuery; use Propel\BOH\EventQuery; use Propel\BOH\VenueQuery; $eventName = $_GET['eventname'] ?? null; if ($eventName) { Util::Redirect('/-/'.urlencode(trim($eventName)), 301); } $s = $_GET['s'] ?? null; // U2 is 2 characters. if (!$s) { Util::Redirect('/'); } if ('/' === substr($s, -1, 1)) { // last character in search is / (not %2F). // redirect to search page without slash. Util::Redirect('/-/'.substr($s, 0, -1), 301); } $s = urldecode($s); $origS = $s; $s = trim($s); if (strlen($s) < 2) { Util::Redirect('/'); } if ($s !== $origS) { // trimming changed the string - redirect to the trimmed version. Util::Redirect('/-/'.urlencode($s), 301); } // also search by processing $s with eric's function. $ericsS = Util::EricsFunction($s); // need a subselect to first get venues with events matching a certain name & with presales. // widening search to %% on request. this is now a 3s query. //e: thisll cut it down a bit for now anyways $subQuery = VenueQuery::create() ->useEventQuery() ->filterByEventName("{$s}%", Criteria::LIKE) //->filterByEventName("%{$s}%", Criteria::LIKE) //->_or() //->filterByEventName("%{$ericsS}%", Criteria::LIKE) ->useTicketQuery() ->filterByPresale() ->endUse() ->groupByEventId() ->filterByEventStartTime(Util::NowUTC('U'), Criteria::GREATER_EQUAL) ->endUse() ->filterByVenueCountry(['US', 'CA']) ->select([ 'venue_city', // these need to be named this way for searchQuery groupBy to work. 'venue_state', 'Event.EventId' ]); // then group the events by city/state $searchQuery = VenueQuery::create() ->addSelectQuery($subQuery, 'a') ->withColumn('count(*)', 'EventCount') ->addDescendingOrderByColumn('EventCount') ->orderByVenueCity() ->groupByVenueCity() ->groupByVenueState() ->select([ 'VenueCity', 'VenueState', 'EventCount' ]); $paginator = new Paginator($template, 12); $paginator->enableCaching(2*3600, 'search-'.md5($s)); //do I read this correctly as 2 hours?? $paginator->paginate($searchQuery); // also get a distinct list of artists who are on events with %searchterm%. // this query is slow (2s) and needs caching. // faster after filtering by event start time, down to 0.4s $wildcardArtistNames = Cache::Get('wildcard-artist-names-'.md5($s), function(ItemInterface $item) use ($s) { $item->expiresAfter(24*3600); return ArtistQuery::create() ->useArtistEventRelationshipQuery() ->useEventQuery() ->filterByEventName("%{$s}%", Criteria::LIKE) ->filterByEventStartTime(Util::NowUTC('U'), Criteria::GREATER_EQUAL) ->endUse() ->endUse() ->groupByArtistName() //->addAscendingOrderByColumn('rand()') ->select('ArtistName') ->limit(12) ->find() ->toArray(); }); // to find image, first look at events. // if no events, look for exact artist match. // if no artists/image, use default. $likelyImage = null; // look for exact artist match. case insensitive search is important since artist_name is _bin (not _bin @todo). $artist = ArtistQuery::create() ->where('lower(Artist.ArtistName) = ?', strtolower($s)) ->findOne(); if ($artist) { if ($artist->getArtistImageLarge()) { $likelyImage = $artist->getArtistImageLarge(); } elseif ($artist->getArtistImage()) { $likelyImage = $artist->getArtistImage(); } } if (!$likelyImage) { // no exact matching artist found. do the search query without pagination and only get images. $likelyImage = EventQuery::create() ->filterByEventName($s) //->filterByEventName("%{$s}%", Criteria::LIKE) //e: don't we want a better chance to match artist name to image? //do we need to stash this someplace to improve the query speed after we find an image? //->_or() //->filterByEventName($ericsS) ->useTicketQuery() ->filterByPresale() ->endUse() ->useVenueQuery() ->filterByVenueCountry(['US', 'CA']) ->endUse() ->groupByEventId() ->filterByEventStartTime(Util::NowUTC('U'), Criteria::GREATER_EQUAL) ->select('Event.EventImage') ->findOne(); } if (!$likelyImage) { // use default $likelyImage = '/images/default-search.jpg'; } $template->assign([ 's' => $s, 'wildcardArtistNames' => $wildcardArtistNames, 'likelyImage' => $likelyImage ]); $template ->setTitle($s.' presales & passwords') ->setCanonical(SITE.'/-/'.urlencode($s)) ->setMetaRobots('follow, index, nocache') ->setMetaDescription("{$s} presale passwords: unlock presale codes for free!"); $template->display('search.tpl');