Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by teppo

  1. Right. Well, you can read the user_id variable from $_SESSION and you can be confident that nothing else will insert it (and it being there means that the user has a valid login session in the other system), would it be enough to check this and perform a redirect to somewhere (home page perhaps) if it's not found from $_SESSION? That'd be the easy way out, anyway πŸ™‚ If you definitely want to log the user in to ProcessWire, you could do that as well, but for that to work you would also need a local (ProcessWire) user. This could be a single user account that's shared by all the users coming from another system, or you could individual accounts for each user. To log the user in with a specific user would be as simple as $session->forceLogin('name-of-the-shared-user'). Individual user accounts would require a few more steps; you'd have to create the user (if it doesn't exist yet), log the user in with it, and so on. If you go with the "real ProcessWire login" approach, keep in mind that these sessions don't automatically have anything to do with the sessions of that other system, so you should also make sure that the external session is still valid, and if not, then log the user out of Processwire.
  2. I don't think I've ever had to do this before, but now that I gave it a quick try, for me it seemed to work right out of the box: // test.php session_start(); if (!isset($_SESSION['user_id'])) { $_SESSION['user_id'] = date('j.n.Y H:i:s'); } echo "User ID for " . session_id() . " " . session_name() . " is " . $_SESSION["user_id"]; // processwire template file echo "User ID for " . session_id() . " " . session_name() . " is " . $_SESSION["user_id"]; ... and the user_id values were the same. Note that you can't start multiple sessions at once, so if you also included the session_start() part in your template file, this is redundant (and might cause an error). At this point ProcessWire has already started the session. If you do this, is the returned value from $_SESSION["user_id"] empty / unset? Technically yes, though I'm not sure how/why that would be useful. Just assign the value: $session->userid = $_SESSION["user_id"]. Note that if you're trying to log the user in based on the user_id value from another system, that's a different question entirely.
  3. This is fixed in the latest release (SearchEngine 0.25.2).
  4. Sorry @snck and @xportde, looks like I completely missed this question. Just to be clear, you mean the ___savedPageIndex() method? Running this when the entire index is being rebuilt should be doable, but it looks like I'll have to move a few bits and pieces to another class. I'll take a closer look at this β€” hopefully later today, or perhaps tomorrow.
  5. As @LostKobrakai and @Jonathan Lahijani pointed out above, ProcessWire's database indeed is relational. I must also admit that I have no idea what some fields being redundant means β€” field tables with no values? Fields that don't have values for a specific page? Something else? Either way this is not something you messed up. Unless you've manually modified the values in the database (or the structure, tables, etc.) the database works exactly as it was designed to work, whether or not your client comprehends how it works or why it was designed that way. Also: reusing fields is the best practice, while creating a new set of fields for each template is something I'd advice against (it's bad for performance, will make selectors less useful, etc.) It's true that in what might be the most typical form β€” particularly for custom-built, one-off applications β€” each table represents a specific content type (pages, blog_posts, users, etc.) ProcessWire's database structure was designed for custom content types, so this "typical form" doesn't exactly apply here. Instead (at the most basic level) we've got a "master" table for pages, and then a new table for each field, connected to the pages table by the pages_id column. Anyway, I believe this has been explained a number of times already, so let's leave it at that. The long story short is that this is how ProcessWire was built to work, and this part cannot be changed. Behind the scenes ProFields Table creates a single database table for each field. So far it's exactly like any other field, but the big difference is that it actually allows one to modify the structure of that table via GUI, while for most other field types the table structure is "set in stone" (defined as codified rules within a Fieldtype module). The main benefit of a ProFields Table field is that it can very efficiently hold multiple (interconnected/related) value items β€” or table rows. A Repeater or PageTable field does the same, but behind the scenes each Repeater or PageTable item is a Page, and each property (subfield) is a field value. Thus the Repeater (or PageTable) approach comes with a different set of constrictions and benefits. (You could reap pretty much the same benefits by developing custom per-field Fieldtypes, but that takes a lot more effort than just creating and configuring a new ProFields Table field πŸ™‚) I sincerely hope that you can convince your client that managing content handled by ProcessWire directly via the database is not the right approach. I definitely get that this is a frustrating situation, both for you and your client.
  6. @Robin S, that works (in some cases) as well, but there are two reasons why I mentioned runHooks: Direct method call will cause an exception if myEvent hasn't been added as a hook method, runHooks won't. In this sort of scenario (events and listeners) the one emitting the event can't reliably know that someone is indeed listening, so this makes more sense. Direct method calls require that the name be a valid method name, runHooks doesn't. Notice how I used 'event-name' in my example? πŸ™‚ First one is really the key reason, second one is just a little quirk that one might find useful, i.e. it's easier to make sure that your event name can't accidentally clash with a real method. Note: runHooks is tagged with #pw-internal. I've used this before in my code because I really needed it, but it's officially not a part of the public API, and thus in case Ryan decides to alter the implementation at some point, there's a chance that code relying on this feature may need revisiting. Just saying. Using only "official API methods" one would have to either check hooks with getHooks before calling the method (directly or via __call()), or just call it and handle possible exceptions with try ... catch.
  7. I must admit that I can't understand all of this. Are you still having problems with the AJAX search feature? If so, it would be helpful to see a bit of code, to see what you're actually doing. Perhaps you could post your search template code and the JavaScript part via https://gist.github.com/ or something?
  8. Sounds like $config->pagefileExtendedPaths would make sense here. Note, though, that I'm not at all certain what will happen if you enable this on an existing site with million pages β€” if you have the chance to create a copy of the site and test there first, that'd be a good idea. Otherwise be sure to take backups of both your site's files and the database before enabling this feature.
  9. Do you mean the part about "$this->runHooks('event-name', $args)"? πŸ™‚ If so, what I meant is that you could register your "listener" by hooking into some non-existing method in the TemplateFile object (or class), and then "emit an event" by running hooks: // somewhere early; prepend file or something: $this->addHook('event-name', function(HookEvent $event) { echo "<!-- I'm " . $event->arguments['what'] . " -->"; }); // alternatively you could add the hook in module or init/ready.php: wire()->addHook('TemplateFile::event-name', function(HookEvent $event) { echo "<!-- I'm still " . $event->arguments['what'] . " ->"; }); // then "emit an event" in the template file: $this->runHooks('event-name', ['what' => 'listening']); It's not quite the same thing, there's no queue, syntax is a bit crude... but as I said before, this might be enough, depending on your actual use case πŸ™‚
  10. A while ago I added an event listener / event queue feature for Wireframe objects: https://github.com/wireframe-framework/Wireframe/blob/master/lib/EventListenerTrait.php. The rough idea is that the object itself keeps track of events and listeners, and if an event is emitted ($this->emit('event-name', $args)), related listeners will be notified. This concept was loosely based on the Vue.js events system. This might be overtly complex for your needs, though. Something as simple as $this->runHooks('event-name', $args) would likely work just fine (though it depends on your use case) πŸ™‚
  11. Hey @eydun! While this could indeed be a potential addition at some point (not making any promises, but will keep this in mind), it's also already doable with a bit of code: if you hook after getItems(), you can add new items to the returned array πŸ™‚
  12. Not sure I fully understand what you're doing, but if you want to submit a search query with AJAX you need to post it to the same URL that you normally would post it to β€” if your search page is /search/, then that's where the AJAX query should go as well. Note, though, that by default SearchEngine responds to GET requests, not POST requests, so that may be one reason why you're not getting the results you'd expect. Might want to switch to jQuery.get() or change the method from POST to GET in your jQuery.ajax() call. Just for the record, SearchEngine has a built-in way to render results as JSON. This is what I typically use for AJAX search features. JSON data is pretty easy to handle with JS, and this way I'm not stuck with whatever markup the search results list on the regular ("full") page is using. When you asked if "Is it possible to realize showing results with AJAX like on the pics", the short answer is "it sure is" β€” but you'll have to create the markup and the JS parts yourself, since SE doesn't provide those out of the box πŸ™‚
  13. $selector = "category=$category, name|text~%=$q, name^=$letter, sort=$getsort"; I must say that I'm a bit confused about all this so might've completely misunderstood your point, but just to clarify: "name" and "text" were table column names, not fields on the page? And you're passing this selector to $pages->find() or pages()->find()? If so, you would need to specify them as subfields: "table_field_name.name|table_field_name.text~%=$q, table_field_name.name^=$letter". The point is that now you're referring to the "name" and "text" fields of the page, not the "name" and "text" columns of a specific table field.
  14. One more addition to this: The API is, in fact, one of the biggest advantages of ProcessWire. While the preferred term is "content management framework", one may as well think of it as an ORM of sorts. ProcessWire was never designed for direct database access, and that's the whole point: it's meant to (mostly) abstract the database layer away so that both developers and content editors can (as much as possible) avoid the complexities and inherent risks of dealing with SQL queries. I must say that I don't agree at all with your point about ProcessWire's advantages taking a backseat once the website is finished. I get where you're coming with this, but I'd assume that we can both still agree that it's extremely rare for a client to actually prefer SQL over a GUI β€” let alone them being competent and meticulous enough to produce data that fulfils all expectations we as developers might have. Obviously we come from different backgrounds and thus have different expectations. If I would've suggested to any of the clients I've ever worked with a platform that requires them to use SQL, that would've been a disaster πŸ™‚
  15. Corrected in my post above. You're right, wires_challenge is in fact a persistent cookie that lasts 30 days. What kind of additional description are you looking for? πŸ™‚
  16. Each field may belong to more than one template, and each template has a different set of fields. Current structure works well with that concept, makes it possible to connect (or disconnect) fields with/from templates with ease, makes it unlikely for a single table to grow to giant proportions (thus making all queries against it slower), and also allows fetching/searching/saving the exact data that ProcessWire needs to fulfil a specific request. So yes β€” there are advantages to current structure. It's also a very fundamental part of ProcessWire, so changing it is not possible without major changes to the core πŸ™‚ It has been. If you'd like to read a bit more on it, I'd suggest doing a google search for something like "processwire database structure". You'll find a lot of existing content on this topic πŸ™‚ Your point of view is not unheard of for newcomers but trust me, there are valid reasons why the database architecture is what it is. Much of it is due to the fact that ProcessWire β€” unlike some competing platforms, I might add β€” was designed with custom data structures (custom fields) in mind from the ground-up. Some other systems (WordPress, for one) have a much simpler database structure, but that's because they weren't originally intended for the same kind of use as ProcessWire. In the context of ProcessWire this would be a bad idea: First of all the Admin is a ready-to-use tool for managing content, and I highly doubt that anyone will really have easier time managing the content with raw SQL. It can be fun and/or if you've had to do that a lot in the past you may be used to it, but still: ask them to give the Admin a try and I bet that this idea will go away in no time. If you manually update the rows in the database, most of what ProcessWire's fields do will be completely skipped. This includes validation, filtering, and sanitization; things that are there to help you build sites with valid and well formed data. Without these features you will run into trouble eventually, it's just a matter of time. ProcessWire does internal cleanups and such using hooks, and those will not get triggered if you update the data manually in the database. This means that you'll likely be left with broken data, missing pieces here and there, and so on. Some fields (take Repeaters for an example) will also be very difficult to update manually via database. Finally, while we're on the topic of hooks: they are a major feature in ProcessWire, used by both core and third party (module) code β€” and, once you get used to it, probably your own code as well β€” and again if you don't go through the "official channels" (API or Admin) you'll loose this benefit altogether.
  17. And also for a11y πŸ˜‰
  18. Probably worth mentioning that since this setting prevents ProcessWire from using unfamiliar hosts in output, it's actually pretty important: Let's say that your server was configured to serve your site with any host that a visitor happens to provide. (I've seen this happen, but admittedly it's a major configuration fumble.) Someone points some-weird-and-perhaps-malicious-domain.tld to your site, and then visits the site using said domain. This could be intentional, or even an accident (again this is something I've seen happen, as weird as it may sound.) Finally some code β€” your own, or perhaps code from a third party module, or even some core feature β€” asks ProcessWire for the full hostname, and makes use of it in output. Now, if the $config->httpHosts setting didn't exist, ProcessWire would have no way to know which domains are valid, and it would just have to trust that the domain specified by the user is indeed a valid one. Any output using this potentially malicious domain could then get cached, leading to various cache poisoning related issues: redirecting other visitors to this domain, or perhaps making the visitor or ProcessWire itself unknowingly send private data there, thus granting a third party access to it.
  19. And from the RFC: While I'd love to give this a try, this limitation is a dealbreaker for me. All the environments I work with host multiple versions of ProcessWire. Might be another reason to move to fully containerized environment... πŸ˜„
  20. Just checking: are you absolutely sure that this method returns only 50 items? Do you have any hooks or modules that could affect this... and are you checking right after, i.e. there's no possibility that the list of items was filtered before you check the number of returned items? $page->children() should return all the children (according to docs too) πŸ™‚
  21. Awesome, thanks @Robin S and @kixe! Manually copying the file and using ImageSizer on it seems like a really nice approach. Don't think I've ever done that myself; in some cases I've accessed Imagick or GD directly, but this is definitely cleaner πŸ™‚
  22. So... this may be a bit of a weird question, but does anyone have brilliant ideas for generating thumbnails for Pagefile (not Pageimage) objects? A bit of background: in a recent project I ran into an issue with this in a situation where there's a files field that contains many different types of files, but for image files it needs to display thumbnails. The problem is that those images are Pagefiles, not Pageimages, so they don't have any image handling features built-in. Current solution involves creating a new Pageimages object and a new Pageimage object, passing the image file to the Pageimage object... and hooking into the install method of said object to prevent duplicate file detection from actually spitting out an endless stream of duplicates. I did consider duplicating image files into another (hidden) field behind the scenes (did that in an even earlier project), but in the end neither solution seems particularly straightforward. What's the state of the art approach for this? I've got this nagging feeling that there's something obvious I've missed πŸ™‚
  23. Just an observation from "an outsider": folks who are not competent in German might still need a German language pack for their projects. It'd be a little difficult to figure out what's going on if the discussion related to said language pack was in German as well. Also, forum guidelines state that the language here is English β€” though personally I don't think it's going to be a major issue if you do decide that German would be better (in this specific context, based on a good reason; the key point being that it would be an exception to the rule) πŸ™‚
  24. Ryan might've had other reasons as well, but... this keeps the textformatter from making a mess out of user-generated content where video URLs could be used in links, within regular text, inside table cells, in image captions, etc. πŸ™‚ That being said, it'd be nice if the module provided a public method for converting known single video URL into an embed code. Currently it looks a little hacky: echo $modules->get('TextformatterVideoEmbed')->format('<p>' . $url . '</p>')
  25. If you look at the first post in this thread, you can see that this module requires a specific format in the texarea ("Converts contents of textarea field..." etc.) If what you've pasted above is literally the contents of your textarea field, then it won't work with this textformatter. Note, though, that this module and Textformatter Video Embed are probably not compatible out of the box due to different format requirements. Depending on your use case you could perhaps use PHP's explode() or preg_split() to split the value of your textarea field into an array (which could then be used in foreach), but it also kind of sounds like a Repeater field would make more sense in this case.
  • Create New...