Jump to content

ryan

Administrators
  • Posts

    16,452
  • Joined

  • Last visited

  • Days Won

    1,453

Everything posted by ryan

  1. I've been looking more and more into the multilanguage (internationalization and localization) capability here. There are two parts to it: 1. Predefined languages for the admin control panel 2. Built-in user defined multilanguage capabilities for sites Number 2 is broader in scope than 1, but it's also something that can be handled at the API level any number of ways. I know Adam and others have been doing this already. Whereas number 1 is something that can't be changed without it being built into the product itself. As a result, number 1 has the priority in the short term, and is actually the next item up on the roadmap. I haven't yet determined what approach we'll take, but am slightly leaning towards structuring it around GNU Gettext, since it's built into PHP and has a track record with other CMSs. That would make the translation process for each language roughly like that of WordPress: http://codex.wordpress.org/Translating_WordPress It would also make the module/plugin implementation of it roughly like WordPress: http://codex.wordpress.org/I18n_for_WordPress_Developers I'm curious what others experience has been with other CMSs with installing and/or translating with different languages? What solutions have you seen that you like, and what have you seen that you didn't like? Thanks, Ryan
  2. Yes, the tags would be parsed in the same manner as ProcessWire selectors, so there would be that consistency in the API access. This is the recommended approach now, though with includes and functions. If I'm understanding you correctly, tags used as definable snippets would make that approach accessible from the tag level, which sounds great. But I see this as always being user defined as to how they want to modularize (perhaps in defining their own tags or templates), because ProcessWire intentionally not get involved in any output generation except in rare cases (like with pagination). For instance, the term "blocks" as it's used in Drupal is an approach I want to avoid because it gets the CMS mixed up into the structure of the markup. It's not necessarily a bad approach -- there are positives and negatives, depending on the intended use. But ProcessWire's concept is the opposite of Drupal's in this regard. However, I think you are using that term in a different way, just to refer to user defined blocks or areas within their template, so that's the way I read it and am agreeable to it. If I'm understanding you correctly, this is about what I had in mind too. But I wasn't planning to have it convert (compile) to PHP code directly, just because the result would have to be eval'd, which isn't an ideal way to execute PHP, unless there aren't any other options. Instead it would identify the function in the tag ($pages->find() in this case) and send everything after it directly to the selector argument of the function. The result would be cycled through the given markup/tags. But I'm going to make note of this for when I get closer to it, as I want to have as many ideas in front of me when implementing as possible. What I think before implementation and during implementation are often very different things. I like the creativity in the idea here. My two concerns would be conflicts with regular use of the API, and how a user would maintain this. But I'll assume there is a solution for the maintenance question. Templates are actually PHP include files rather than files that are eval'd separately (like in some other CMSs). Templates are likely to include other templates. A user can assume in their template file that it is a blank slate for building a PHP application. ProcessWire can be used as a PHP framework with lots of functions provided to it. Or you can even pretend that ProcessWire isn't there in your template code... using it like a blank PHP script that has it's own URL and some variables provided to it. But this flexibility necessitates that we don't make assumptions about what they are doing in the code. If we have alternate compiled versions of templates, suddenly PHP vars like __FILE__ would fail and relative includes would fail, among other things. Still, I appreciate the idea and will keep thinking about this to see where it might be applicable in the future. For instance, maybe a module could provide this capability and people would use it with the understanding some things may be a little different from the PHP side. I like this thinking! But I should note that PW is already ready to output any format. It doesn't get involved in output generation. It has no idea that it's used to output HTML most of the time. It provides the data to your template, and your template decides how to output it. So having output of RSS/XML, JSON, etc. at the core level goes against the concept of the CMS. But having that in modules or user-defined templates is consistent with the concept of the CMS. What I believe you are describing are modules (perhaps called as tags) that output in different formats, and that's always good. But I'm not totally sure I'm reading you right, so I'll just put in a short snippet of how we would currently make a page template that outputs a list of it's children in either HTML or RSS (determined by a GET var). Then maybe you can post an equivalent tagged example, if available. <?php $children = $page->children(); if($input->get->rss) { $rss = $modules->get("MarkupRSS"); $rss->title = "Children of " . $page->title; $rss->render($children); } else { include("./head.inc"); echo $children->render(); // or foreach for your own output include("./foot.inc"); } Thanks, Ryan
  3. The passwords in ProcessWire are not reversible (unless you keep a copy of them somewhere else), so you would need to email a password reset email, as opposed to a feature that emails them their actual password. This is something that will be included with the new user system. However, if you wanted to do it now, you would have a "forgot password" link that they click on. It would click to a page with a template that would look up the email address for the user (email address stored per our earlier thread) and it would send them a special URL where they can reset their password. Likely it would be the same URL as the "forgot password" page, but with a special token in the URL to identify that they really did receive the email. There are a lot of security considerations with a feature like this that go beyond the scope of what may be practical to write in code here, but the actual password resetting part is the easiest part: $user = $users->get("user's name"); $user->pass = "user's new password"; $user->save(); You will want to be very careful before resetting the password to ensure that the user really is who they say they are. Because ProcessWire doesn't have email addresses in it's current user system, there isn't any way for it to confirm that the person really is who they say they are in a lost password function (which is why there isn't one). But since you are storing email addresses (per our earlier thread) it will be possible for you to implement a password reset function. When someone requests a password reset, you will email them a URL with a sufficiently complex randomly generated code as a GET var. I recommend something like sha1(microtime() . mt_rand() . $email). You will also want to store that code locally with the user in a new field, as well as in $session (i.e. $session->code). When they click the URL to your site (from the email they received), the template handling that page will examine the code and verify that it matches up with the code stored with the user, and likewise matches up with the code stored in $session. Now give the user a form where they can enter a new password, and set a new $session variable with the same code but under a different name, like $session->confirmed_code, and make $session->code blank. Once submitted, get the confirmed_code from the $session and find the user that has it stored. Change the password to the one they submitted (per the PHP snippet above). Be sure to remove the password reset code from the user's record in the database, and unset $session->confirmed_code. This is roughly the approach that will be taken with ProcessWire's new user system, but with a couple extra security checks (code expiration for one).
  4. Glad that worked. Thanks for posting the final code too. The only other thing you'll want to be mindful of is when you delete a user, you'll also want to delete the associated page (just to keep things organized). I can show you how to create a module that hooks into the user deletion and handles the page deletion. Or you can periodically foreach the /members/ pages and check if there are any extras there. As you know, the users system is being redone. There are a few reasons, but one of them is that the system is designed just to have a few users in there, primarily for administrative purposes or for role placeholders for another user system. If you start getting hundreds of users in there, it's going to affect performance. In the new system, it won't matter how many users there are, since they will be built on top of the pages system.
  5. Glad you like ProcessWire! Nice work on the site. The duplicated tree does seem like an easy to manage approach. Though if your pages are simple, and you only needed to support a couple languages, I would think that a duplicated field approach might also be good, because you could edit the two translations together on the same page. So you might have these fields in your template: headline_en headline_fr body_en body_fr And then just display the one that corresponded to the language you wanted to show. To determine the language, you could use one of the approaches Adam mentioned, or the approach I mentioned in the previous message. Or, if you didn't mind having the en/fr segment at the end of the URL, you could just look at the first url segment: /some/url/fr/ For this URL, the page is actually /some/url/ and the 'fr' part is what you added to the URL when generating it or linking to it. <?php if($input->urlSegment1 == 'fr') { $headline = $page->headline_fr; $body = $page->body_fr; } else { $headline = $page->headline_en; $body = $page->body_en; } echo "<h1>$headline</h1>"; echo $body;
  6. I will put some thought into this and come up with a more official roadmap to place on the site. Thanks, Ryan
  7. In this case, you'll want to use the 'more' link that appears at the bottom of the list. Keep clicking 'more' until you have the page you need to move in view, along with the place you need to move it in view. Then drag it to where you want it. If working from the main Page List, you can also drag the page you want to move to a temporary place, then drag it back to the new location once it's in view.
  8. I think that I must have added a special case to the login process. If you could disable the login for the guest role, then you would essentially close your site off to edits and prevent yourself from being able to login. It should probably be the case with the logout role too, but this particular login/logout process was really made more for administrative use. I recommend making your own login/logout templates for non-administrative use.
  9. This thread might have some more useful stuff too: http://processwire.com/talk/index.php/topic,37.0.html I didn't realize there was a need for more, but I can definitely add more. I can see the value with what you are mentioning here. Another possible way to handle a /en/ or /fr/ at the beginning would be to install ProcessWire in a directory named /en/. Then create a symlink on your file system called /fr/ that points to /en/. Your template code could examine the URL it's being loaded at to determine which version of content to show: <?php if(strpos($_SERVER['REQUEST_URI'], '/fr/') === 0) { echo $page->body_fr; } else { echo $page->body_en; } I haven't actually tried it, but I think it would work.
  10. Thanks, I will definitely need help testing. Also wanted to mention that you can always take the approach mentioned here: http://processwire.com/talk/index.php/topic,54.msg917.html#msg917 This essentially duplicates what you could do with the new user system (in the areas you are describing), though it just takes more work on your part. Also see this thread too, for another approach: http://processwire.com/talk/index.php/topic,17.0.html Thanks, Ryan
  11. Thanks for taking the time to write this up. I think what you are describing is very similar to what I'd like tagscript to progress to in terms of capability, so I appreciate having this written in more detail. My thought is that you will be able to define a new {tag} either with a function (like in that module above), with a separate module, or by pasting the tagscript snippet into an admin field (which doesn't yet exist, but will be built as a module). If you have the tagscript module installed, it will always translate tagscripts in you templates when you enable it. You'll also be able to selectively turn it on for any custom fields (like if you wanted to enter tags in your bodycopy or something). Being able to turn it on in custom fields is one area where I think tags bring something very useful to the table... you wouldn't ever want to enable PHP in a field, whereas I'd have a much higher comfort level (security wise) with enabling tags in a field. In terms of syntax, let me know what you think of this? Tagscripts can be simple like: {tag} Tags can have arguments, like: {tag, name="value", name="value"} Or tags that translate directly to an API function, and be "open", allowing you to create the markup (the closed version would generate it's own markup): {pages.find parent=/news/, featured=1} <li><a href="{url}">{title}</a> {date}</li> {/pages.find} That would be the equivalent of: <?php foreach($pages->find("parent=/news/, featured=1") as $item) { echo "<li><a href='{$page->url}'>{$page->title}</a> {$page->date}</li>"; } I like the open-tag approach, where you can define your own markup. I'm less comfortable with tags that output markup on their own (level 2 templates, as you described them), but also recognize that not everyone wants to recode the markup for everything, all the time. That's why the pagination and comments modules generate markup... because I don't want to have to code that markup for every site. So that's an admission of value for tags that output markup, but I think you always have to be careful with anything that's generating markup you didn't write. So my though is that for any given tag, you can write a closed version like {tag} that generates it's own output, or you can write an open version (like in the example above) or {tag} ... {/tag} where it uses what's in between for output, allowing you to substitute additional tags to obtain the raw values of fields within the {tag} ... {/tag}. I believe this is similar to the approach that Expression Engine tags with it's tags. When working on a site that involves a team of people responsible for design/development, you are absolutely right about this. For most of the sites I work on lately, it's just me building it and then maintaining it over time. But that's a unique situation, and not how it works half of the time in other work environments. I would agree that tags would be preferable with the site you are describing. While I personally find native PHP solutions simpler and easier to maintain for my own use, I would be inclined to use tags in situations where I knew other designers/developers were going to be making edits too. I plan to keep ProcessWire's core always PHP API based, but am very enthusiastic about building/collaborating on a module that can make the API fully accessible to tags, and let users define their own tags/snippets in a format that is easy to do and easy to share among sites. I think this will broaden ProcessWire's appeal with one of it's main target audiences (designers), though you said it better than me. Thanks, Ryan
  12. Rebecca, thanks for your feedback. I think what you are saying makes sense. ProcessWire is a new project and ideas are valuable and important. As far as voting goes, maybe we need something more official, but when a lot of people join in and say they want something, that goes a long way (I guess this is like voting).
  13. ProcessWire won't ever stretch or squeeze an image, so no matter what dimensions you give it, you can count on it to maintain the proportion of the actual photo subject while still maintaining the dimensions you've given it. If you need to deal with a gallery of photos, all with different dimensions, then your best bet will be to feed $image->size($w, $h) your target dimensions, and most likely the result will be a good one. If you need a fixed width AND height for your automated thumbnails, I've found that cropping/sizing to the center is the only way to deal with unknown dimensions ahead of time. And that's why ProcessWire does this. The only exception I could think of is if you are dealing with photos that always have the subject weighted to some corner, though I've not had to deal with that situation before. Of course, if you only need to maintain one dimension (whether just width, or just height) then all of this is a non issue. But give it a try, I think there is a strong possibility that you'll like the result.
  14. Well the API to the users system probably won't change much, if at all. As you've seen, it's already nearly identical to the $page interface. So when you upgrade, I think best case is that it'll still work, but you'll have some unnecessary code. Worst case is that you'll need to convert your new pages in /tools/users/ over to the new users system (which you may want to do either way). But it won't be hard, and I think we'll be able to get you through the conversion with just a few API snippets.
  15. The new user system will provide better support for developing your own user registration functions. But it's probably still a month or so before I'll have that ready. In the new user system, users are actually pages, so you can interact with them, add fields to them, and so on, in the same way.
  16. You are doing it correctly, but it looks like I gave you bad advice. It did support undefined fields within a user at one time in the past, but looks like it's no longer the case (I just spent some time in the code to confirm). I apologize for accidentally telling you something incorrect before. The whole users system is being converted to pages as the next item on my to-do list, so the users system is fairly barebones at present, as you can tell, and I've left some things out of it as a result. What I would suggest is that you start using pages to store your user information now. Setup a new page to serve as the parent for users, like /tools/users/, and remove the guest role from that page so that it's not publicly accessible. Create fields for email, order_id, ipaddress, amount, signupdate and add them to a new template you create (user.php or something like that). Then change your code: $u = new User(); $u->name = $username; $u->pass = $password; $u->addRole($role); $p = new Page(); $p->parent = $pages->get("/tools/users/"); // you define where you want them $p->template = $templates->get("user"); $p->name = $username; $p->email = $email; $p->order_id = $order_id; $p->ipaddress = $ipaddress; $p->amount = $amount; $p->signupdate = $signupdate; $u->save(); $p->save(); Then when you retrieve a user, retrieve it's corresponding page for your info: $u = $users->get("$username"); $p = $pages->get("/tools/users/$username"); Taking it further, you could also make a function that loads users and would automatically populate your page fields into the $user object. In this way you could interact with the $user object like in the example you posted. But you would just want to use these functions below to get and save users, rather than the built in ones: <?php function getUser($username) { $u = wire("users")->get($username); if(!$u) return false; $p = wire("pages")->get("/tools/users/$username"); foreach($p->fields as $field) { $u->set($field->name, $p->get($field->name)); } return $u; } function saveUser(User $user) { $p = wire("pages")->get("/tools/users/" . $user->name); if(!$p->id) $p = new Page(); $p->name = $user->name; foreach($p->fields as $field) { $p->set($field->name, $user->get($field->name)); } $u->save(); $p->save(); } Then you could access your fields in the same way as in your original example. These are just rough examples typed directly in the browser, so they haven't been tested and you would just want to use them as a starting point rather than as a complete solution.
  17. If you ask for an image of 100x100, then it's always going to return an image exactly that size. For a 400x200 source, the result would be scaled to 200x100 then cropped to 100x100 (though I think it does it in one step). It always crops to the center. I will make it able to crop to corners if anyone ever needs it (I personally haven't needed it yet). You asked about a 100x50 image too. If you wanted it to return a thumb of your 400x200 image at 100x50, then you'd want to do this: $thumb = $image->size(100, 50); Or if you just wanted it sized to 100 pixels wide, and a proportional height: $thumb = $image->width(100); Or if you just wanted it sized to 50 pixels tall, and a proportional width: $thumb = $image->height(50); The above 3 snippets would produce the same result (100x50) for a 400x200 image.
  18. Okay I think that's it then. 'data' is a field name used internally by ProcessWire. It should have given you an error about that, but it looks like I hadn't yet added this to the list of reserved words. I'm adding it to the list, so thanks for finding it! Ryan
  19. Glad that you figured this out. Thanks for posting the solution.
  20. I think you are right about the sessions dir. That could definitely account for the issue you are describing. You might want to edit /site/config.php and change "$config->debug = false;" to "$config->debug = true;" to confirm it. The only other possibility I can think of is if you have turned off the trailing slash in your admin template. The admin template requires the trailing slash. Technically it's possible to turn it off by editing the admin template, and that could cause this same issue you are experiencing. You can tell if this is a problem by looking at the URL when you are on the admin login page. If it is "/admin/" then no problem, but if it's "/admin" (no slash) then that could be a problem. However, I'm guessing it's more likely the sessions directory issue you mentioned.
  21. Thanks Abu, that would be great. We're still a little ways off from having multi language capability in the admin, but it is one of the high priorities on the roadmap, so hopefully we can tackle this soon.
  22. The title field will likely get locked down (required field name) in the near future, just because I think it'll make life a little more difficult for module developers if we don't... for example, without a known title field, there would be no way to identify what the actual title of a page is, just the URL name. As a result, I don't recommend changing the name of the title field.
  23. Not yet, but the user system is actually being converted to a type of pages, so you'll have a lot of control over this, as well as the same level of flexibility that you have with pages. This is under construction, so not yet on the live source.
  24. By any chance do you have a field named 'data' in your list of custom fields?
  25. Thanks for this info. I am not near a computer today (other than this cellphone), but will find and fix this error tomorrow. It appears that the error is happening in the core rather than due to a specific API call, so I'm assuming this is a bug, and should be easy to fix once I get back to the office.
×
×
  • Create New...