From bcd246076540a8353fa55fc0a5e19343c1a2dbc9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 14 Aug 2015 13:03:08 +0200 Subject: Implement package search service mockup --- brep/package-search.cxx | 154 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 brep/package-search.cxx (limited to 'brep/package-search.cxx') diff --git a/brep/package-search.cxx b/brep/package-search.cxx new file mode 100644 index 0000000..3317d43 --- /dev/null +++ b/brep/package-search.cxx @@ -0,0 +1,154 @@ +// file : brep/package-search.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include // make_shared() + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace cli; +using namespace odb::core; + +namespace brep +{ + void package_search:: + init (scanner& s) + { + MODULE_DIAG; + + options_ = make_shared ( + s, unknown_mode::fail, unknown_mode::fail); + + db_ = shared_database (options_->db_host (), options_->db_port ()); + } + + void package_search:: + handle (request& rq, response& rs) + { + using namespace xml; + using namespace web; + using namespace web::xhtml; + + MODULE_DIAG; + + params::package_search pr; + + try + { + param_scanner s (rq.parameters ()); + pr = params::package_search (s, unknown_mode::fail, unknown_mode::fail); + } + catch (const unknown_argument& e) + { + throw invalid_request (400, e.what ()); + } + + // @@ Would be nice to have a manipulator identing string properly + // according to the most nested element identation. + // + const char* ident ("\n "); + const char* title ("Package Search"); + serializer s (rs.content (), title); + + s << HTML + << HEAD + << TITLE << title << ~TITLE + << STYLE(TYPE="text/css") << ident + << ".package {margin: 0 0 0.5em;}" << ident + << ".name a {text-decoration: none;}" << ident + << ".summary {font-size: small;}" + << ~STYLE + << ~HEAD + << BODY; + + string q ( + pr.query ().empty () ? "" : "q=" + mime_url_encode (pr.query ())); + + transaction t (db_->begin ()); + + // @@ Use appropriate view when clarify which package info to be displayed + // and search index structure get implemented. + // + using query = query; + auto r ( + db_->query ( + "ORDER BY" + query::name + + "OFFSET" + to_string (pr.page () * options_->results_on_page ()) + + "LIMIT" + to_string (options_->results_on_page ()))); + + for (const auto& p: r) + { + s << DIV(CLASS="package") + << DIV(CLASS="name") + << A + << HREF + << "/go/" << mime_url_encode (p.name); + + // Propagate search criteria to the package version search url. + // + if (!q.empty ()) + s << "?" << q; + + s << ~HREF + << p.name + << ~A + << ~DIV + << DIV(CLASS="summary") + << p.summary + << ~DIV + << ~DIV; + } + + t.commit (); + + if (pr.page () || r.size () == options_->results_on_page ()) + { + s << DIV; + + if (pr.page ()) + { + s << A + << HREF << "/?p=" << pr.page () - 1 + << (q.empty () ? "" : "&" + q) + << ~HREF + << "Previous" + << ~A + << " "; + } + + // @@ Not ideal as can produce link to an empty page, but easy to fix + // and most likelly will be replaced with something more meaningful + // based on knowing the total number of matched packages. + // + if (r.size () == options_->results_on_page ()) + { + s << A + << HREF << "/?p=" << pr.page () + 1 + << (q.empty () ? "" : "&" + q) + << ~HREF + << "Next" + << ~A; + } + + s << ~DIV; + } + + s << ~BODY + << ~HTML; + } +} -- cgit v1.1