-
Posts
214 -
Joined
-
Last visited
Everything posted by SteveB
-
The "equal" you use to assign a value is "=" the one you use to compare values is "==" so what you meant to do was... if ($category_active == $thisCategory){
-
Problem with hook in modified PageRender
SteveB replied to SteveB's topic in Module/Plugin Development
You were right about get(). The hooks work fine but the caches don't clear after editing the page because they get created with the md5 "secondary" kind of id and clearing of the cache this way uses the simple page id cache filename. In PageRender, what do you think about having clearCacheFile() use $cacheFile->removeAll() (instead of $cacheFile->remove()) if the numbered file isn't there? if($cacheFile->exists()) { $cacheFile->remove(); if($this->config->debug) $this->message("Cleared cache file: $cacheFile"); } else{ $cacheFile->removeAll(dirname($cacheFile)); if($this->config->debug) $this->message("Cache file does not exist: $cacheFile, removed all cache files for that page."); } //Also do same for $cf in the conditional loop of parent pages FYI, using 2.3 dev, PageRender V102 Wish list: It would be nice if generation of secondary id (in PageRender) was more accessible to the programmer, so we could more easily cache different versions of a page. We might have want to use an md5 of the whole $options array or something like that. -
Why? Almost everything can be relative to document root or the current page and arranged the same way locally and on the server. If something really must be in different places, manage that path info from one central spot. You could put those in /site/config.php as long as you are careful not to use any system names. People have their own ways of doing things but personally I think it's well worth the minimal effort to keep data and files as portable as possible. I haven't been using PW very long but I haven't seen anything turn up that would be a problem. If I'm missing something please correct me. I wouldn't want to get caught out by that.
- 30 replies
-
- 1
-
- deployment
- tools
-
(and 1 more)
Tagged with:
-
Problem with hook in modified PageRender
SteveB replied to SteveB's topic in Module/Plugin Development
I haven't sorted out those questions but I simplified the code. It's working well but cache is still sticky. All my non-standard stuff is done from the PW Template file. I use my module but don't take on any of the caching tasks or hook anything. I'm using template caching but not on any of the sub-renders (there's not much to be gained by that). Works nicely and is simpler but the cache still doesn't clear when the page is saved. The purpose of the module is to provide a method which recurses out from the current page to other pages following parent/child and possibly other relationships, producing markup and saving it as properties of the pages. It also makes some data about what it found. The pages render their markup differently according to the level of recursion and other parameters passed down to them through $options. Pages involved in this scheme must load the module from their template files. Callback functions customize recursion and layout on a per template basis. In my test, it's only looking at child pages and only one level down. With 20 child pages speed's okay, 50 feels too slow. Of course it's super fast when cached. -
Problem with hook in modified PageRender
SteveB replied to SteveB's topic in Module/Plugin Development
It extends WireData, as do Page and PageRender. I did try (briefly) extending from PageRender. It also has issues with how $this has been defined. What happens is that my method calls $this->isCacheAllowed($page) (a method in PageRender) and then isCacheAllowed does if(!$this->user->isGuest()) and we get Call to a member function isGuest() on a non-object (line 88 of E:\dev\vhosts\pw\wire\modules\PageRender.module). -
I wrote a module which adds a new rendering method to Page using a hook. I wanted it to be able to do caching like the PageRender module does. Various "non-object" issues cropped up. The best I could come up with was to copy the cache related methods from PageRender into my module and fuss around with it. It works nicely and it does cache the pages but hooks for clearing cache after page save/delete don't work. I can clear cache manually from the module's interface in admin though. I'm happy to have gotten it to this point but I'm doing something wrong in the hook/module/OOP. Tried a few things. Comparing my module to PageRender module, the methods supporting caching are the the same (except for $this/wire issues explained below) but the renderPage() method is renamed and different. My replacement method keeps the parts about $options and recursion but the whole block of code about $output is replaced. Clue: There is something funny about $this. It also seems wrong that I've hooked to Page but the cache support I need is in PageRender. I tried hooking PageRender's renderPage and using $event->replace = true; but I didn't get it to work. I could revisit that if anyone thinks it makes sense. I started looking to see how a Page object ends up calling PageRender methods but it's kind of a wild goose chase. In the module's init(): $this->addHook('Page::foo', $this, 'foo'); $this->pages->addHookAfter('save', $this, 'clearCacheFile'); $this->pages->addHookAfter('delete', $this, 'clearCacheFile'); If I do that I get: Error: Call to a member function addHookAfter() on a non-object If I use wire("pages") instead of $this->pages there's no error but it doesn't do anything: $this->addHook('Page::foo', $this, 'foo'); wire("pages")->addHookAfter('save', $this, 'clearCacheFile'); wire("pages")->addHookAfter('delete', $this, 'clearCacheFile'); Similarly in isCacheAllowed() I had to change $this->user->isGuest() to wire("user")->isGuest(). Also $this->input->pageNum in getCacheFile(). If I try to call PageRender::isCacheAllowed($page) instead of having my own copy I just get a non-object error happening there. The easiest thing seems to be to make a replacement for the PageRender module but that seems wrong. How do I do this properly?
-
I usually keep the order info separate from the payment info. The payment info is mostly about the transaction with the service handling the actual payment and is linked in the database to the user and the order. I put failures and error messages in there too because now and then one needs to compare that to a customer's story.
-
Trying to figure out pros and cons of using this module because I'm doing something where I have a selector saved in a Page's text field and then do the find at render time. The module would have done that find, giving me a PageArray to use in the render. But I see that the find is done by runSelectorQuery() which is called by the wakeValue, sleepValue, loadPageField hooks. I'm new to a lot of this fieldType/hook stuff but isn't it redundant to do the find in the sleepValue hook?
-
This is perhaps an obvious feature creep suggestion but you might want to add the option to remove "noise words" like a, the, of, etc. There are lists on the net. These are words that are too common to be meaningful keywords.
-
Care to elaborate on that?
-
I need to check out that Foundation profile (and Zurb). You may want to revisit the Blog profile later on. A lot of generally useful techniques I had read about on the forum turn up there. Tags, Categories, Comments and nice examples of factoring out page builds (widgets etc.)
-
It was a off-topic of me to bring it up in the first place but I was thinking of some kind of anonymous tag or category, I just wanted the member pages of the group to be able to find each other. I've put that on hold and am doing it in a non-reciprocal way with each page having a Multiple Page Reference Field it can use to list pages it should link to. If I want that to be a reciprocal arrangement I imagine some code hooked to page saving could notice that A points to B and then make B point to A. The use/case for anonymous group is: Group some pages, p1, p2 Group some other pages, p6, p7, p8 Render page p8, and it can show links to the other pages in its group, p6 and p7. Likewise the pages in the other group link to each other. The groups should work without a lot of fuss over what they are called. I suppose it could be done like tags but they don't need titles so having pages for them seems like overkill. The idea about hooking additional behavior onto the way I'm doing it now seems more appealing in terms of administration etc.
-
Okay so we're not just talking about "public-facing pages" but if there were to be a fancy validation tool I suggest that it be capable of helping with that side of things too. Something to assemble JS validation scripts and corresponding server side validation, in a neat programmatic way. Doing the easy validations client side is great. You still have to sanitize and check when the data comes in but doing it client side is so quick. I've used PEAR QuickForm (kind of a beast in some ways). That has a generic JS validation library (load it once) and then it generates a small script specific to your form. Of course you have to tell it what rules need to be applied to what. Sometimes it's just as easy to do it all by hand but it can be pretty neat for big forms. Maybe do the low hanging fruit (regex tests mostly) and use callbacks or something for anything else.
-
I use $options to pass settings TO the renderer (some of this is recursive) and I suppose I could pass things back (&$options?) but since the action of rendering is more about the Page it seems intuitive to pass things through the Page, using distinct names. The render engine I'm using at the moment (not a final decision) is StampTE. If I change my mind about which one to use only one method in my class is affected (the templates too of course). Right now I'm wondering how best to implement something with PageArrays where the pages in the array just need to be able to find each other. Unlike a tag, we aren't accesing it by name. The pages it connects wouldn't know what name to use. I'm calling this a "ring" and the idea is that when any one of the items in the ring is selected to be on a page it will be displayed with little subrenders (maybe just links) for other items in that ring. It's kind of like those "You might also like" suggestions you see on shopping sites. I know how to find whether a Page is in a PageArray but how do I find which of several PageArrays contain a given page?
-
I'm basically a programmer with some design skills.Jumped on the PW bandwagon recently. You can do a lot with relatively few concepts. You just have to use those PW parts to good advantage. My first shot at something in PW tends to have some workarounds in it by the time I get all the functionality I want. Then I look at those issues more closely and dig around in the forums and find that I missed some subtlety and was making extra work for myself. One thing that helps me is to just think "node" whenever the Processwire "Page" is discussed. They really are anything you want to them to be, or at least they function as a handle for connecting PW's powerful API to data you bring in. Very practical. The cheatsheets and other references behind the API link up top are a great help.
-
Several weeks later... I have a Version Two of this which I like better. It's using the hook and module approach in Apesia's MarkupRenderHelper. The scenario I have is a bunch of pages in a tree, each of which uses a selector to select certain "item" pages which are all lurking under a single parent elsewhere in the tree. Any page can show any items. When rendering a page we recurse one level down to make little displays from the child pages, and we find the selected items and render little boxes for those too. Thus we have items displayed and informative navigation for drilling down. For anything more than very basic output I like to use a template engine (as opposed to straight PHP/HTML). I used Smarty for a long time, but now I tend to use a three part setup with a simple cut/paste/search/replace template engine in the middle. Driving it is a PHP method with just ifs and foreaches and lines of code to work the template engine. The third piece is the HTML template files. Many of the day to day "little changes" clients ask for get isolated in those places which keeps the other code clean. I'm using 2 modules. One is for configurable settings and some utilities. The renderer is in the other one, which is autoloaded (conditional autoload by template name soon). The PW template file gets an instance of the settings module, puts that in the $options array, and passes that to the renderer. The renderer starts with a "prep" method, one for each kind of page, to get data ready for the layout and stash it in arrays. Some of that is just grabbing fields but there's navigation and comments to get ready, etc. If that preparation resulted in lists of subpages and items to render, another method does that and finally a layout method works the template system. We pass a few things back and forth through the Page objects. That's how we pass paramters to influence the secondary rendering and then recover the rendered oputput. The filenames of (non-PW) templates are based on the PW template name. If we are recursing, the depth is added to that (we stop at 1 so that makes 4 different files). Finally, the pages and items have a "style" field which lets you specify an alternate set of these templates to use just for certain ones. That may be decided automatically too. The gift of Blog Profile: This is reaching the point where I show an early demo to a few people to fish for comments before I get too far along. What better way than to drop it into a Blog? So, I took the Blog Profile pretty much as is, put a fixed piece of content on the home page and messed with the commenting so it's off until you login. When you are logged in you only see comments that you or the admin posted. That makes it more of a one on one demo. If something comes up which needs to be shared I can write a blog postabout it. Eventually we end up with something like documentation. I'll let you know how it goes.
-
Ryan: All good with the latest dev version. I had started this with the "stable" code and the Blog Profile. Then I realized I needed a feature from the dev version and I had a copy of dev that was about month old sitting on my hard drive. I dragged the wire folder over to my project. That gave me the feature I needed and mostly wortked but I had the non-object error. I downloaded a new copy of the dev version on 6/21, dragged the wire folder in and that fixed it. Soma: Re. "normal login practice" Having come to PW fairly recently I look for examples to see what the common idioms are. If I see similarity in how people go about a process, especially such a universal one as logging in, that tells me something. All I was saying is that I hadn't seen much on the topic until I found Ryan's post. P.S. I'm impressed with the high signal to noise ratio of this forum and PW itself.
-
Maybe it's me but I had a hard time finding a description of "normal" login practice on PW. That post of Ryan's seemed like the best overview. Will follow some other leads. Okay, the error goes away when I switch back to the production version. Unfortunately I need a feature from the dev version. Looking into that now. SOLVED: I downloaded the current dev version, dropped that in and that fixed it. The register form and the login form both work and the user is indeed logged in.
-
I'm using a login page based on Ryan's helpful post Stripping it down a bit this is what happens when submitting form to register a new user: $username = $sanitizer->username($input->post->username); $pass = $input->post->pass; $u = new User(); $u->name = $username; $u->pass = $pass; $u->addRole('guest'); $u->addRole('demo_viewer'); $u->save(); $u = $session->login($input->post->user, $input->post->pass); $u = $session->login($username, $input->post->pass); This is the code for subitting a login form: if($user->isLoggedin()) $session->redirect('/profile/'); if($input->post->username && $input->post->pass) { $username = $sanitizer->username($input->post->username); $pass = $input->post->pass; $u = $users->get($username); $u = $session->login($username, $pass); } Both cause this error when we do $session->login Error: Call to a member function has() on a non-object (line 47 of E:\dev\vhosts\pwb\wire\core\User.php) The user does get created and both roles do get added. $session is an object before we try $session->login Any ideas? Oh, I'm using PW 2.3.0 Dev version downloaded 5/15, if that matters. Edit: Fixed error Adrian spotted but it made no difference.
-
Merge existing data with a new profile-based site?
SteveB replied to SteveB's topic in Themes and Profiles
The method for migrating pages mostly worked. FYI, the bit of code in the middle to make the CSV file needs to use html_entity_decode on the conent it gets from Pages Web Service. I'm putting this together on my Win7 desktop and the only real problem I had may be Win related; the import from CSV complained it could not copy the images into the newly created item's asset folder. The paths were right. Afterwards I used the admin pages to add those images and that was fine. That may fix itself when I move it to a real server (Linux). The next gotcha was that I forgot that having $options passed along through recursive rendering only works with Dev version of PW. With that sorted out, my demo is inside a pretty much standard Blog Profile site. I modified the home page to have fixed content in the middle instead of recent posts. I tested using the blog system's category navigation within my demo and that works nicely. A good thing since integration with CMS is one of the project's features. The demo has its own bare-bones templates and CSS so as not to get too carried away. Initial purpose is to sound out my clients about the more functional and structural features. -
Merge existing data with a new profile-based site?
SteveB replied to SteveB's topic in Themes and Profiles
That could be useful but for now, I'll setup fields and templates by hand (not enough to bother with automation). Then migrate the items from system A to system B with help from existing modules. Do it by installing Pages Web Service on system A, Calling that from a script which takes the json info and write out a csv file representing the items. Then on system B using Import Pages from CSV files to create the pages from that csv. I have to stop now but I'll report back. -
Merge existing data with a new profile-based site?
SteveB replied to SteveB's topic in Themes and Profiles
I think the key thing is to use the API to recreate templates, fields and pages. Direct data transfer is okay for a whole site but will break things if done piecemeal (clashes of ids etc). One could come up with tool and for a semi automated process like... Start at the top of a tree of pages Run through it looking for templates Run through those looking for Fields Check that the necessary fields and templates can be made on the destination system or are there and seem identical. - manual intervention - Setup Fields Setup Templates Run through the pages - some intervention and cleanup may be needed - PW maintains a unique index between the page name and the parent_id and adds a number to the end to (smith, smith1, smith2...). Page ids and possibly names may end up different than they were on the source system. This might require attention depending on the situation but seems unlikely to be a big problem. For my current situation it makes sense to setup the templates and fields by hand. The pages are under a couple of root parent pages so they are not going to clash with anything. Still this seems like the kind of thing where having a strategy in place for "partial migration" could payoff later. -
I have a vanilla 2.3.0 PW site where I've created an early demo of a project. It would be great to have my demo on a PW installation with the Blog Profile so I can use that as a project blog, get comments from potential users, collaborators etc. Is there a way to create a new bloggy PW installation and migrate my Templates, Fields, Pages, etc. to it? Is there a way to graft the Blog Profile onto to my existing PW installtion without wiping out or breaking my project? My demo is only about 20 PW pages, a few files, and whatever data that has created. I could setup a new installation with Blog Profile and manually reconstruct my demo. I guess I could write a csv export tool for my pages, then setup templates, fields, etc. in the admin, move files around and use the csv import tool. I can imagine this kind of thing coming up in the future with big content though and I'm hoping to learn what my options are. I do remember seeing a thread pondering how to update a live site from a dev version which had started as a clone of the live site. Are there tools and practices to help with moving part of one site into another? Thanks
-
Autoincrement a certain field of a certain template
SteveB replied to owzim's topic in API & Templates
Sometimes I setup a table for counters... CREATE TABLE counters ( count int(10) unsigned NOT NULL DEFAULT '0' , name char(10) NOT NULL , PRIMARY KEY (name) ); And a function like this: function bumpCount($mysqli, $name){ if($result = $mysqli->query("UPDATE counters SET count = LAST_INSERT_ID(count+1) WHERE name = \"$name\"")){ $count = $mysqli->insert_id; if($count>0) return $count; //normal if($result = $mysqli->query("INSERT INTO counters (count, name) VALUES (1, \"$name\")")) return 1; //initialize new counter } return false; } And use it like this: $mysqli = new mysqli('host', 'user', 'password', 'database'); echo 'The counter is: ' . bumpCount($mysqli, 'foo'); If anything goes wrong it returns false. New counters are setup automatically when you use a new name. First number issued is 1. The usual disclaimers about code examples apply. -
It looks like overkill because it's just a "Hello world" kind of thing to make sure all the parts connect. That was an excercise in synthesizing a bunch of threads about pages and templates and rendering and adding a bit of my own baggage to prove to myself that I could start with the basic PW template file (PHP/HTML) and progessively add bells and whistles without losing any standard functionality. My clients often ask for some simple thing which may stay simple or may grow. After feature creep an MVC approach becomes more appealing. The question of whether to use a template engine (and which one) depends on the situation. I use different ones (or none) for different reasons. In the test, the view uses a template engine but nothing outside of the view has any knowlege of that. Similarly nothing outside of the PW template file is aware that MVC is being used. The test had rendering of subpages only to demonstrate that those additions don't break normal PW trickery. Have your cake and eat it too. So, that's sufficient for getting started. Now I'm mulling over issues around categories and the admin page tree vs site structure vs information structure. I'll be working on catalogs and e-commerce which I've done before and consequently have opinions about and favored ways of doing things. I'm happy to see the Shop-for-ProcessWire work-in-progress but my first impressions (that's two disclaimers if you're counting) are that it leans a little towards depending on having anticipated everything. I think I'll go in a different direction for some things and try for compatibility with it in other areas. Ryan, I'll check blog profile. Glad I found PW. Your code is a pleasure to read and the API-centric approach is a huge plus. Great ore in the forum too. It might be good to put a sticky thread in Getting Started about certain common nouns which are special in the PW context (Page, Template, Field...). There are plenty of good posts to draw from such as this one on pages. Thanks.