-
Posts
17,232 -
Joined
-
Days Won
1,699
Everything posted by ryan
-
Build Site on Localhost server - How easy to Transfer database
ryan replied to NooseLadder's topic in Getting Started
I always develop in a subdirectory and usually launch to root. While Page Link Abstractor is one way to resolve that, an even simpler way is to do a search/replace on your DB dump file before importing it to your live server/root installation. I use TextWrangler (free version of BBEdit), but any quality plain-text editor should work. So lets say you were developing a site locally in /subdir/ and you wanted to update all the /subdir/ links to be / (root) instead: Search for: ="/subdir/ Replace with: ="/ This should cover all <a> and <img> tags, like <a href="/subdir or <img src="/subdir. -
The LanguagesPageFieldValue (and getLanguageValue function) are only applicable to multi-language fields. The only multi-language fieldtypes there are at present are TextareaLanguage, TextLanguage and PageTitleLanguage. Language alternate fields are an entirely different thing. It is nothing more than one field substituted for the other. For instance, 'image_de' would be substituted for 'image' when the user's language is 'de' and 'image_de' is populated. That's all there is to it. There aren't any other classes or functions to think about behind the scenes with language alternate fields. With language alternate fields 'image' and 'image_de', if you don't want fallback of 'image' to 'image_de' to occur when 'image_de' is populated and the user's language is 'de', then turn off output formatting, or retrieve the value with $page->getUnformatted('image'); Your example was trying to retrieve the value in 'de' regardless of the user's current language. So if that's what you are trying to do, then just access 'image_de' directly, i.e. $img = $page->image_de; or a non-language specific version: $img = $page->get('image_' . $user->language->name);
-
That's correct. But note that these language alternate fields can be used with any fieldtype. So there's not really any reason to use them with TextLanguage, TextareaLanguage or PageTitleLanguage. They are an alternate way of doing multi-language fields.
-
That's great if Twig is keeping track of knowing when to clear cache files. I see no problem with putting them in /assets/cache/twig -- that seems like the best place. I look forward to checking out your implementation!
-
Here's the next version of the Blog Profile. This one incorporates the simpler structure I mentioned earlier, exactly as outlined. Please let me know how it works for you. To install, download a fresh copy of ProcessWire and replace the /site-default/ directory it comes with, with the one in the attached zip: blog-site2.zip Thanks, Ryan
-
Definitely interested--keep it up! Regarding cache, I'm assuming it creates compiled templates and it's the PHP code that it's caching, not the content? If that's the case, there's not much use in trying to hook into PW's cache timing because it's all for output caching. You'd need something that can tell when a template file or template settings have changed and clear the cache then. PW has the ability to store dynamic info with each template, and I think we'd need to keep track of the file modification time for each template file, as well as the template modification time. Then when it sees that the file (or template) modification time is newer than the one saved with the template, it would clear the cache. Not sure how to do it just yet, but think we can figure it out. Let me know if this sounds consistent with what would be needed to you?
-
I have the next version ready. I just need to export the profile and double check it all works. I hope to be able to post it later today after getting through some client work.
-
Best practice for staging to live database synchronization
ryan replied to evanmcd's topic in General Support
Good points. The #1 idea sounds interesting and I like where you are going with that, though I don't think it's safe to consider the meta data independent from the content to the point where it would be safe to version them separately. The recorder modes (#2 & #3) would be great if it weren't for the issue of primary keys you mentioned, but maybe there are places where it could still work. I think that anything that involves merging two versions of the same site has to treat the other's data as totally foreign. Things like IDs have to be thrown out unless you are giving all ID generation authority to one or the other. Personally, I have never seen this as a particular problem to be solved because I've never seen the ability to do it, never expected to be able to, and not sure I could ever trust it if it existed. Nevertheless, I'm enthusiastic about exploring the possibility. But I'd be scared to death of having to provide support for such a feature. Something that I've got a higher comfort level with are specific import/export tools. For instance, a tool that enables me to connect my PW install with another, and browse the fields, templates and pages. Then I can click on "import" and have that field, template or page(s) created on my system too. If there's some matter of meta data to be resolved (like a new page reference with non-existing parent), then I know it then and there and can adjust my import sequence accordingly. If I'm modifying data rather than importing, then I can have the opportunity to see and confirm what's going to happen before it takes place. If we're talking about going between two servers that can't talk to each other, then copy/paste of JSON data from one to the other in the developer's browser is another way to accomplish it. This process seems more supportable because the individual site developer still has some ownership over what's happening. -
It sounds like you are triggering the language alternate fields. Assuming you have the LanguageSupportFields module installed, it'll be looking for any field names that end with a language name, like "_en" in "header_image_en". If it finds another field that has the same name, but no language (like "header_image"), then it assumes your "header_image_en" field is a language alternate field. Meaning, it'll substitute that field for "header_image" when it sees that the user's language is "en".
-
Inputfieldmodule doesn't autoload their js/css
ryan replied to apeisa's topic in Module/Plugin Development
Any modules that extend: Inputfield, Process or ModuleJS will auto-load their CSS/JS files if they have the same name as the module and appear in the same directory. However, in order for that to work, their init() method has to be called. So if your module extends one of those, and has an init() method, then make sure to call the parent init() method: public function init() { parent::init(); // ... then your code } -
I'm not sure that the W3 validator is picking it up right either? Seems like it is showing the whole thing as double entity encoded. Also tried loading in Safari, and it can't seem to read the feed correctly either. Firefox seems okay. Definitely something unusual going on with this feed, but I am not familiar enough with this particular format to know what's wrong. W3 validator isn't helping much since it's seeing the whole thing as double entity encoded.
-
Welcome to the forums abe.izar. Seems like they should make json_encode at least attempt to typecast an object to a string (which would convert to IDs here). Maybe I can update wireEncodeJSON (a front-end to json_encode) do that. However, if you really want to export pages and all their data to JSON, here's how you can do it: function pagesToJSON(PageArray $items) { $a = array(); foreach($items as $item) { $a[] = pageToArray($item); } return json_encode($a); } function pageToArray(Page $page) { $outputFormatting = $page->outputFormatting; $page->setOutputFormatting(false); $data = array( 'id' => $page->id, 'parent_id' => $page->parent_id, 'templates_id' => $page->templates_id, 'name' => $page->name, 'status' => $page->status, 'sort' => $page->sort, 'sortfield' => $page->sortfield, 'numChildren' => $page->numChildren, 'template' => $page->template->name, 'parent' => $page->parent->path, 'data' => array(), ); foreach($page->template->fieldgroup as $field) { if($field->type instanceof FieldtypeFieldsetOpen) continue; $value = $page->get($field->name); $data['data'][$field->name] = $field->type->sleepValue($page, $field, $value); } $page->setOutputFormatting($outputFormatting); return $data; }
-
Alan the $comment->page will only point to the actual comment's page if the comment was retrieved with FieldtypeComments::findComments. Part of what that function does is populate the appropriate $page variable to all the comments it finds. However, you can still get it even if you don't have the latest PW or aren't using that findComments function: $page = wire('pages')->get($comment->pages_id);
-
The PageLinkAbstractor is also a 3rd party module, and not one that I would try to build around at all. If something doesn't work with that module, then I would just say the two are not compatible with each other. I don't think many people are actually using that PageLinkAbstractor module anyway. I don't personally use it. If I've been developing a site in a subdirectory and then launch it to the root on another server, I just do a simple search+replace on the DB dump file, using a text editor (TextWrangler/BBEdit) replacing "/subdirectory/" with "/". However, this is something that I do plan to add core support for. The plan is that FieldtypeTextarea will encode local links to IDs like {123} when saving, and then unencode them back to URLs at runtime. We can collaborate on making everything work together when the time comes. I think I understand the problem you mentioned with a link created in TinyMCE being a static link in the language of the user making the edit. Would it be possible to just disable the URL parsing when the user is inserting a link? if(wire('process') == 'ProcessPageEditLink') { // don't parse URLs } else { // do parse URLs } The point of the above is so that the URL is always stored in the default language. Then hook into FieldtypeTextarea::formatValue and have it hunt down and replace them with the current language specific version, at runtime. I'm not so familiar with how the language localized URL module works, so this is based on guesses, but it might work something like this: public function init() { $this->addHookAfter('FieldtypeTextarea::formatValue', $this, 'hookFormatValue'); } public function hookFormatValue(HookEvent $event) { $language = wire('user')->language; // no need to continue if user's language is default if($language->isDefault()) return; $page = $event->arguments[0]; // not using, but here if you need it $field = $event->arguments[1]; // not using, but here if you need it $value = $event->arguments[2]; $rootUrl = rtrim(wire('config')->urls->root, '/'); // find links if(!preg_match_all('{href=[\'"]([-_./a-z0-9]+)}[\'"]', $value, $matches)) return; foreach($matches[1] as $key => $url) { // slice off subdirectory if site is running from one, so we have a clean URL from PW-install root if($rootUrl && strpos($url, $rootUrl) === 0) $url = substr($url, strlen($rootUrl)); // see if this is a link to a PW-managed page in the site $linkPage = wire('pages')->get($url); if(!$linkPage->id) continue; // now that you have the $linkPage and know the $language you should be able to // get the language URL right? I don't know how you do it, so I'll pretend: $langUrl = $this->getLanguageUrl($linkPage, $language); // replace the default language URL with the language URL $value = str_replace($matches[0][$key], "href='$langUrl'", $value); } $event->return = $value; }
-
That's a good idea! And it's already there. But you have to be logged in to see it. See the sidebar, it says "create new blog post". You always have great suggestions, but sometimes it takes me awhile to get it. After sleeping on it and thinking more on the intended audience here and want it to be as broad as possible. So while I want this to be something that people don't have to touch any code, I also don't want to introduce any unnecessary barriers for people that do. Given what you've suggested, I'm thinking I will tear into it and make it less nice on the code side, but simpler for someone to figure out without having to invest much time in it. Here's the strategy: $markup, $output and $blog will get moved into 1 API variable just called $blog. That API variable will be moved to a module and won't be something that people ever have to look at the code for. The functions in it are: findPosts($selector) getPost($selector) findComments($selector) findRecentComments($limit) setOutput('content|sidebar|whatever', $value) renderPosts($posts) renderComments($comments) renderCategories($categories) renderSubnav($items) renderArchives($year) renderAuthor($author) renderWidgets($widgets) render() // main Rather than having the Markup class, all those render functions map to PHP "views": renderPosts() uses view file: /site/templates/blog/posts.php renderComments() uses view file: /site/templates/blog/comments.php ...and so on: subnav.php archives.php author.php widgets.php main.php Those view files are basically like WordPress templates. Though with no classes, functions or logic. Just markup, loops and variables. The render functions figure out the logic and then just hand the views data that's ready to be output. Not quite as flexible as before (though still flexible), but there's nothing to figure out, so I like that. The template files in /site/templates/ will remain largely the same, other than that they'll be calling on $blog rather than $markup and $output like they are now. What I think this leaves us with is a minor compromise, though one that has a much lower development barrier to entry. People can get in there and adjust the markup output without having to know anything about the system. So I think it's a good compromise. Structurally I think it may be better too because it's much easier to see the scope of a theme: the entire /templates/ dir (and other dirs in it) is it. This setup is kind of similar to the approach some of us use in having common render functions as modules. Like having a PageArray::renderVillas() that is used by multiple template files. The main difference here is that the render() functions are taking care of any needed logic and then letting really simple "view" files handle generating the actual output. So now the "theme" has good separation and hopefully encourages people to create new themes. It's not an approach I'd use on one of my projects, but it should be a perfect approach for this blog and encouraging people to customize it.
-
$pages->get() will always return a Page object, so rather than doing this: if($type_of_oper) { you should do this: if($type_of_oper->id) { When a $pages->get() doesn't match anything, it returns a NullPage. The easiest way to check for a NullPage is by seeing if it has an id, like above. Though you could also do this if you preferred: $p = $pages->get($selector); if($p instanceof NullPage) { // no page found } else { // page found }
-
It was dropped before going into the core just because timestamp is already the native storage state of all date fields. When output formatting is off, date fields are always timestamps. When output formatting is on, you can get the timestamp of any date field like this: $page->getUnformatted ('field_name'); So I figured that having an output formatter that returns an unformatted state probably wasn't worthwhile.
-
Use something other than $user for this: $user = $sanitizer->username($input->post->user); That overwrites the $user API variable in your template file, so better to use something like $username or $name or the like. It's probably not the issue here, but still something to fix just for good measure. What is the URL in your browser window? When you access that URL independently of a login, do you get something different?
-
AlexV, what was the output of your $selector (in the <h2>?). The code looks good to me, but I don't know the full site structure either, so don't necessarily have the context to relate it to that.
-
I like your idea of adding a "wire" template language! We can just stop referring to it as PHP and then all of the sudden people will see: wow this is a really easy template language.
- 74 replies
-
- 3
-
-
- template engine
- twig
-
(and 8 more)
Tagged with:
-
Thanks for testing Apeisa and Sinnut. Right now the intended audience is us, as you might guess from the included blog entries. But once everything is worked out with it, the intended audience is folks that want to write blog entries and don't know how to do any development. That's the audience that we have no connection with at all right now, but is WordPress's biggest audience. I'm not too worried about this audience understanding the PHP side of it, because I want to make it technically unnecessary for them to have to do anything at that level. But in order to best support that audience, I also think there needs to be some abstraction on the code side. I did start out with a structure a lot more like the basic profile. But after working with it a bit, decided to build this in the best and most efficient way I knew how. We're already covering the basics in the default site profile, but don't have anything out there that shows how to build something for larger scale. While this isn't particularly large scale, I decided to approach the profile from a development perspective in the same way I'd approach a site I'm building for a client. Though I'll usually bundle some of this stuff into modules, distancing it from the site templates. I may still do that, but still debating the merits of it in this case. Another factor here is that I wanted to support really easy theme-ability, where you'd never have to make the same change in more than one place. If you want to make this thing run on Twitter Bootstrap rather than Zurb Foundation, all you need to do is replace a few classnames at the top of the file (in the constructor). If you want to make all images follow HTML(5) rather than XHTML syntax, then you only need to change it in one place, and so on for any tag. I didn't want to commit 100% to one CSS framework over another, so trying to keep some things abstracted here so I could swap in another framework without having to change the code. For the sidebar widgets, I'm thinking about taking a module approach for those rather than a template one. That way people could install a new widget (as a module) in one shot rather than having to add a template, add fields to it, and create a page for it.
-
Here's the first version of the blog site profile. I was wondering if anyone could help me test? To install, download a brand-new copy of ProcessWire (it must be the latest commit). Then remove the 'site-default' directory that it comes with, and replace it with the one in the attached zip file. Then load in your browser to begin installation as normal. Edit: see this message for the latest version. Thanks, Ryan
-
Addition of some items into a Pagefield field via api
ryan replied to AlexV's topic in API & Templates
Just a quick note about output formatting. You always want it on before outputting anything. This ensures that when you output $page->title (for instance) that characters like '&' will get entity encoded to '&', and the like. Whereas, if you were setting values to the page, you'd want it to store '&' rather than '&'. So updating an earlier example, you'd want to do this: echo "<a href='{$p->url}'>{$p->title}</a> " ; // output formatting should be ON here since you are echoing output. // now you want output formatting OFF, since you are setting values and saving a page: $p->of(false); // same as setOutputFormatting(false), shorter syntax. $p->subway_station = $pages->get("/subway_station/sub_st_0111/"); $page->save();