Jump to content

Skyscrapers Profile


ryan

Recommended Posts

Okay, I think it isn't working because new site profiles have a little bit different structure (an information file, with name, image, etc. for example). 

I think the solution will be to install PW 2.3 (or 2.4), install it and update PW. (Give me some minutes, I'll try that for you)

Link to comment
Share on other sites

Okay, I think it isn't working because new site profiles have a little bit different structure (an information file, with name, image, etc. for example). 

i tried to make some kind of information file like in other profiles, but it didn't work for me . not that you should not try anyway 

btw i also tried blog profile which was working without problem

Link to comment
Share on other sites

  • 2 months later...

I am using AMPPS on my computer but it only allows me to install the basic install. I looked to install it manually but the 2.5.2 folders do not match up with the 2.3 structure. I would try to install 2.3 and then do upgrades but I can't find the 2.3 version.

Anyone know where to place these files or could there be an update on this thread?

Thanks

Link to comment
Share on other sites

  • 2 months later...

Hello!

 
I'm trying to add an additional field "Categories".
Created field "shopcats" in Admin> Setup> Fields.
Created 2 templates (shopcat.php and shopcats.php), similarity of templates (architect.php and architects.php).
In menu i created  page "Categories of stores" with template shopcats.php.
And also created a category pages with template shopcat.php (Clothes, Furniture, Household appliances, ...).
In template "skyscraper" I added a field "shopcats".
As a result, displays only the category ID. How to display the category name?
How to add a search by category in a search engine?

3e616962bf71.jpg

<?php

/***************************************************************************************
 * SHARED SKYSCRAPER FUNCTIONS
 *
 * The following functions find and render skyscrapers and are defined here so that
 * they can be used by multiple template files. 
 *
 */

/**
 * Returns an array of valid skyscraper sort properties
 *
 * The keys for the array are the field names
 * The values for the array are the printable labels
 *
 * @return array
 *
 */
function getValidSkyscraperSorts() {
	return array(
		// field => label
		'images' => 'Images', 
		'title' => 'Title', 
		'parent' => 'City', 
		'shopcats' => 'Category', 
		'height' => 'Height', 
		'floors' => 'Floors', 
		'year' => 'Year',
		); 
}

/**
 * Find Skyscraper pages using criteria from the given selector string.
 *
 * Serves as a front-end to $pages->find(), filling in some of the redundant
 * functionality used by multiple template files.
 *
 * @param string $selector
 * @return PageArray
 *
 */
function findSkyscrapers($selector) {

	$validSorts = getValidSkyscraperSorts();

	// check if there is a valid 'sort' var in the GET variables
	$sort = wire('sanitizer')->name(wire('input')->get->sort);

	// if no valid sort, then use 'title' as a default
	if(!$sort || !isset($validSorts[ltrim($sort, '-')])) $sort = 'title';

	// whitelist the sort value so that it is retained in pagination
	if($sort != 'title') wire('input')->whitelist('sort', $sort); 

	// expand on the provided selector to limit it to 10 sorted skyscrapers
	$selector = "template=skyscraper, limit=10, " . trim($selector, ", ");

	// check if there are any keyword searches in the selector by looking for the presence of 
	// ~= operator. if present, then omit the 'sort' param, since ProcessWire sorts by 
	// relevance when no sort specified.
	if(strpos($selector, "~=") === false) $selector .= ", sort=$sort";

	// now call upon ProcessWire to find the skyscrapers for us
	$skyscrapers = wire('pages')->find($selector); 

	// save skyscrapers for possible display in a map
	mapSkyscrapers($skyscrapers); 

	// set this runtime variable to the page so we can show the user what selector was used
	// to find the skyscrapers. the renderSkyscraperList function looks for it. 
	wire('page')->set('skyscraper_selector', $selector);

	return $skyscrapers; 
}

/**
 * Serves as a place to store and retrieve loaded skyscrapers that will be displayed in a google map.
 *
 * To add skyscrapers, pass in a PageArray of them. 
 * To retrieve skyscreapers, pass in nothing and retrieve the returned value.
 *
 * @param null|PageArray $items Skyscraper pages to store
 * @return PageArray All Skyscraper pages stored so far
 *
 */
function mapSkyscrapers($items = null) {
	static $skyscrapers = null; 
	if(is_null($skyscrapers)) $skyscrapers = new PageArray();
	if(!is_null($items) && $items instanceof PageArray) $skyscrapers->add($items);
	return $skyscrapers; 
}

/**
 * Render the <thead> portion of a Skyscraper list table
 *
 * @internal
 *
 */
function renderSkyscraperListHeader($showCity = true) {

	// get the 'sort' property, if it's been used
	$sort = wire('input')->whitelist('sort');
	if(!$sort) $sort = 'title';

	// query string that will be used to retain GET variables in table header sort links
	$queryString = '';

	// make a query string from variables that have been stuffed into $input->whitelist
	// to use with the table header sort links
	foreach(wire('input')->whitelist as $key => $value) {
		if($key == 'sort') continue; 
		$queryString .= "&$key=" . urlencode($value); 
	}

	$out = "\n\t<thead>\n\t<tr>";

	// build the table header with sort links
	foreach(getValidSkyscraperSorts() as $key => $value) {

		// don't show a city header if we're already in a city
		if($value == 'City' && !$showCity) continue; 

		// check if they want to reverse the sort
		if($key == $sort) {
			$key = "-$sort";
			$value = "<strong>$value »</strong>";

		} else if("-$key" == $sort) {
			$key = ltrim($sort, '-'); 
			$value = "<strong>$value «</strong>";
		}

		$out .= "<th><a href='./?sort=$key$queryString'>$value</a></th>";
	}

	$out .= "\n\t</tr>\n\t</thead>";
	return $out; 
}

/** 
 * Render a table/list of the given $skyscrapers
 *
 * @param PageArray $skyscrapers Skyscrapers to render
 * @param bool $showHeader Should the <thead> with sort links be displayed? default=true
 * @return string The rendered markup
 *
 */
function renderSkyscraperList(PageArray $skyscrapers, $showHeader = true) {

	if(!count($skyscrapers)) return "<h3>No skyscrapers found.</h3>";

	// we don't show the city if they are already on a city page
	$showCity = wire('page')->template != 'city'; 

	// get the markup for any pagination links 
	// note: these are provided by the MarkupPagerNav and MarkupPageArray modules, 
	// modules that are already installed by default. 
	$pagerLinks = $showHeader ? $skyscrapers->renderPager() : ''; 	

	$out = 	$pagerLinks . "\n<table class='list_skyscrapers'>";
	if($showHeader) $out .= renderSkyscraperListHeader($showCity);
	$out .= "\n\t<tbody>";

	// build the table body
	foreach($skyscrapers as $skyscraper) {
		$out .= renderSkyscraperItem($skyscraper, $showCity); 
	}
		
	$out .= "\n\t</tbody>" . 
		"\n</table>" . $pagerLinks;

	// if we stuffed a variable called skyscraper_selector into the page,
	// tell them what the selector was, for demonstration purposes
	$selector = wire('page')->skyscraper_selector; 
	if($selector) {
		$out .= "\n\n<p class='selector_note'>The selector used to find the pages shown above is:<br />" . 
			"<code>" . makePrettySelector($selector) . "</code></p>\n";
	}

	return $out; 
}

/**
 * Generate the markup for a single skyscraper item in a skyscraper list
 *
 * This is primarily used by the render() method. 
 *
 * @param Page $skyscraper The Skyscraper to render
 * @param bool $showCity Should the city name be shown?
 * @return string
 *
 */
function renderSkyscraperItem(Page $skyscraper, $showCity = true) {

	// we keep track of the number of items we've already rendered	
	// so that we can alternate placeholder images from row to row
	static $cnt = 0;
	$cnt++;

	// make a thumbnail if the first skyscraper image
	if(count($skyscraper->images)) {
		// our thumbnail is 100px wide with proportional height
		$thumb = $skyscraper->images->first()->width(100); 
		$img = "<img src='{$thumb->url}' alt='{$skyscraper->title} photo' />";

	} else {
		// skyscraper has no images, so we'll show a placeholder instead
		$class = 'placeholder';
		if($cnt % 2 == 0) $class .= " placeholder2"; // for alternate version of placeholder image
		$img = "<span class='$class'>Image Not Available</span>";
	}

	// make a truncated version of the bodycopy with max 500 characters
	if($skyscraper->body) {
		$summary = strip_tags($skyscraper->body); 
		if(strlen($summary) > 500) { 
			$summary = substr($summary, 0, 500); // display no more than 500 chars
			$summary = substr($summary, 0, strrpos($summary, ". ")+1); // and truncate to last sentence
		} 
		$summary = trim($summary); 
	} else $summary = '';

	// what we show when a field is blank
	$na = "<span class='na'>N/A</span>";

	// start a table row for the output markup
	$out = 	"\n\t<tr class='skyscraper_details'>" . 
		"\n\t\t<td rowspan='2' class='skyscraper_image'><a href='{$skyscraper->url}'>$img</a></td>" . 
		"\n\t\t<td><a href='{$skyscraper->url}'>{$skyscraper->title}</a></td>"; 

	if($showCity) {
		// display the city's abbreviation, or title if there is no abbreviation
		$out .= "\n\t\t<td>" . $skyscraper->parent->get("abbreviation|title") . "</td>" . 
		"\n\t\t<td>" . $skyscraper->get("abbreviation|shopcats") . "</td>" ;
	}

	// finish the table row of output markup
	$out .= "\n\t\t<td>" . ($skyscraper->height ? number_format($skyscraper->height) . " ft." : $na) . "</td>" . 
		"\n\t\t<td>" . ($skyscraper->floors ? $skyscraper->floors : $na) . "</td>" . 
		"\n\t\t<td>" . ($skyscraper->year ? $skyscraper->year : $na) . "</td>" . 
		"\n\t</tr>" . 
		"\n\t<tr class='skyscraper_summary'>" .
		"\n\t\t<td colspan='6'><p>$summary</p></td>" . 
		"\n\t</tr>";

	return $out; 
}

/**
 * Make the selector better for display readability
 *
 * Since we're displaying the selector to screen for demonstration purposes, this method optimizes the 
 * selector is the most readable fashion and removes any parts that aren't necessary
 *
 * This is not something you would bother with on a site that wasn't demonstrating a CMS.  
 *
 * @param string $selector
 * @return string
 *
 */
function makePrettySelector($selector) {
	if(preg_match('/(architects|parent)=(\d+)/', $selector, $matches)) {
		if($page = wire('pages')->get($matches[2])) 
			$selector = str_replace($matches[0], "$matches[1]={$page->path}", $selector); 
		if($matches[1] == 'parent') $selector = str_replace("template=skyscraper, ", "", $selector); // template not necessary here
	}
	return $selector; 
}


Link to comment
Share on other sites

  • 1 year later...

Hello @cyberderf,

there is not an tutorial available for this profile, except the blog post about the new demo site. In this blog post there are some of the new functions explained, which were used in this profile, but if you wan't to know more, you will have to dig through the code. Keep in mind, that this an advanced site profile. If you haven't worked with delayed output before, you should first read this tutorial;)

Regards, Andreas

  • Like 1
Link to comment
Share on other sites

I don't know, you will have to ask the developer of this site profile @ryan.

Probably it will be ok, because after all the site profile is available on a public GitHub repository and the visuals are mostly realized with the framework UIkit.

But it will be best, if you ask him or at least give credit to his work if you plan to reuse it. ;)

  • Like 1
Link to comment
Share on other sites

Hi everyone,

I looked at the code from the skyscraper demo page and found it really helpful.

But on the frontpage I wanted to insert some keywords to the input field and got some mixed feelings about it. The point is: you have to put the exact text phrase into it to get a better result.

So the search for "tower located in chicago" has other results (two) than the results for "tower chicago" (two, but different). As I understand is: user will fill in any kind of random words into it and think the search for "tower chicago" has the searched pages for "tower located in chicago" too, because the two words are inside that text too, right?

I know the search example is small and a show for beginners, but it hurts on the user experience side, what could result in bad experience. Maybe changing the label "keywords" to something else would be fine and a fast fix?

kindly regards
godmok

Link to comment
Share on other sites

6 hours ago, godmok said:

...So the search for "tower located in chicago" has other results (two) than the results for "tower chicago" (two, but different). As I understand is: user will fill in any kind of random words into it and think the search for "tower chicago" has the searched pages for "tower located in chicago" too, because the two words are inside that text too, right?

I know the search example is small and a show for beginners, but it hurts on the user experience side, what could result in bad experience. Maybe changing the label "keywords" to something else would be fine and a fast fix?

In respect of the demo itself, that's an interesting point you raise (since keywords do not necessarily have to be next to each other). In respect of your own use, you can change the search (selector) operator at this line in search.php. Here's a list of all the available operators. Not all of them will be relevant in this case. As per your suggestion, you want  ~= Contains all the words.

  • Like 2
Link to comment
Share on other sites

8 hours ago, godmok said:

So the search for "tower located in chicago" has other results (two) than the results for "tower chicago" (two, but different). As I understand is: user will fill in any kind of random words into it and think the search for "tower chicago" has the searched pages for "tower located in chicago" too, because the two words are inside that text too, right?

The %= operator matches part words (which can be desirable) but all the characters in the search string must be in the given order in the searched fields. When I want to match part words I will usually explode() on the space character and then match against each word as a separate clause in the selector.

$selector = '';
$search_terms = $sanitizer->selectorValue($input->get->search);
if($search_terms) {
    $search_terms = preg_replace("/\s+/", " ", $search_terms); // replace multiple spaces with single space
    $terms = explode(" ", $search_terms);
    foreach($terms as $term) {
        $selector .= "title|body%=$term, ";
    }
    $matches = $pages->find($selector);
}

 

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Would it be possible for someone to bundle up the skyscrapers 2 profile with relevant install/modules? I'm brand new to ProcessWire and I've made a couple of attempts without luck. It'd be great to test out the new site and hopefully learn something whilst breaking it! Thanks.

  • Like 1
Link to comment
Share on other sites

21 minutes ago, DonPachi said:

Would it be possible for someone to bundle up the skyscrapers 2 profile with relevant install/modules? I'm brand new to ProcessWire and I've made a couple of attempts without luck. It'd be great to test out the new site and hopefully learn something whilst breaking it! Thanks.

https://github.com/ryancramerdesign/skyscrapers2

Link to comment
Share on other sites

  • 2 months later...

Obvious newbie here.

I'm having a heck of a time trying to install the Skyscrapers Site Profile out of the box. I first tried following the instructions explicitly, replacing everything in the site-default directory with everything from the Skyscrapers Site Profile, but when I tried to run the PW installer on it, it wasn't on the list of available profiles.

So, next, I restored the original site-default directory and started over. On my next try, I replaced config.php, the install directory, the modules directory, and then dropped the contents of the Skyscraper templates directory in the corresponding directory in site-default.  This time the profile showed up as an install option. It ran through the installation process and seemed to work just fine:

  • Database connection successful to skybase
  • Saved configuration to ./site/config.php
  • Imported database file: ./wire/core/install.sql
  • Imported database file: ./site/install/install.sql
  • Imported: ./site/install/files => ./site/assets/files/
  • Created directory: ./site/assets/cache/
  • Created directory: ./site/assets/logs/
  • Created directory: ./site/assets/sessions/
     

I was prompted for admin info input, which I did, selected the cleanup checkboxes, and hit "continue."

 

Now I'm getting this error:

 

Quote

Fatal error: Uncaught Error: Class 'ProcessWire' not found in /path-to-my-installation/site/config.php:19 Stack trace: #0 /path-to-my-installation/wire/core/ProcessWire.php(874): require() #1 /path-to-my-installation/index.php(33): ProcessWire\ProcessWire::buildConfig('/path-to-my-installation/...') #2 /path-to-my-installation/install.php(107): require('/path-to-my-installation/...') #3 /path-to-my-installation/install.php(1276): ProcessWire\Installer->execute() #4 {main} thrown in /path-to-my-installation/site/config.php on line 19

 

What do I need to fix?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...