Hi,
I am using this very good and robust module to allow my authenticated users to organize their favorite nodes into folders. Therefore, a user can create a flag, and when flagging an node with a specific tag, this node is considered as filed in a folder.
Now, I want to tags created by this user to be usable only by this user. Is this possible ? I guess, by looking at the current code, that this not a feature, yet.
Are there other people interested in such a feature.
A first approach would be to add a column uid to the flags table, et change the following functions:
- flag_access
- flag_user
- flag_add_form

and maybe a few more. Some may say I didn't get the concept of Flag, but ok, it's a very good base to develop the requested feature. Or maybe is there any other module I should consider that would be more suited to my requirements ?

Thanks

CommentFileSizeAuthor
#18 flag_custom.tar_.gz7.33 KBawolfey

Comments

kha’s picture

Maybe an idea : add a role at the same level as authenticated user, that could be entitled "flag creator"

I could do the development, but I would need some help to make it a pacth.

quicksketch’s picture

A lot of this would be possible with #322034: Have a $flag->access() method, at least on the user-facing functionality. However, you'd also need to setup quite a bit of access surrounding setting up flags, since there is only a single permission for "administer flags". I'm not entirely sure if this module is appropriate for your requirements, but I can't think of others that would get any nearer.

kha’s picture

Ok, I did the alteration of the flag module.
- It adds a "private flag" checkbox on the admin screens.
- the flag is visible and usable for the creator
- I added and Express flag form to allow the quick creation of a standard private flag
- I changed the $flag->access method to handle "privates" flags
- I added the uid in the flags table
- I had to drop the "Unique" constraint on the name, the unicity now comes with the uid
- I changed the install script in accordance.

It works fine, and was definately much faster to do it that way than to rewrite a module from scratch. Anyway, having done the development, I am quite convince that this is not the same module anymore. So if anybody is interested, just send me a message, I would be glad to give away my code.

gausarts’s picture

Any update?

I'd love this feature for a different need, though.

I want to make a comment is flaggable only by the comment author. Say, I want to create a pro or contra arguments based on comment.module since the other debate modules are not ready yet for drupal 6 this far. So whenever a comment author clicked a pro option, he is in a pro side, etc. No other people can change his choice.

Will that be possible with the proposed feature from #3, or did I miss anything from the docs and issue queues? Please throw me a light. Thanks

quicksketch’s picture

This won't be possible until #322034: Have a $flag->access() method is completed. I would highly suggest avoiding the approach taken in #3 however, since Flag module has an extensive future before it, and you'll be locked out of any further updates by forking.

colin_young’s picture

Will the future updates to Flag address the features in #3? I'd like to see user private/created flags and a template for automatically creating them (e.g. user clicks on "create new flag" and gets a form to fill in a name with the rest being created from a template using tokens to create the other required text). Is that something envisioned for the future, or should I be looking to create an additional module (in the same vein as Flag_weight)?

UPDATE: As an example of what one might do with this feature, Amazon wish lists are a perfect example.

Thanks.

Colin

mitchell’s picture

Version: 5.x-1.x-dev » 6.x-1.x-dev
Component: Code » Miscellaneous

@kha: Could you please post your code? It may not be committed to flag core, but you could still upload a tar of it here.

Marked #420134: Allow users to create custom per-user flags and #346955: Allow custom flag names per user as duplicates.

philbar’s picture

This feature in flag will help me replace Nodequeue and Smartqueue per User.

+1 from me.

aaronbauman’s picture

+1

BenK’s picture

+1

TC44’s picture

+1

Kane’s picture

+1

quicksketch’s picture

Please do not post any more +1s for the sake of my sanity.

The functionality requested in #4 will be added in #285237: Ability to disallow a flag/unflag operation and isn't really related to this issue.

The functionality requested in #3 (essentially Amazon-style wish lists) needs more fleshing out in terms of how it should be implemented. Making a separate entry in the flags table for every user-specific flag does not seem like a very scalable approach, since all flags are loaded on every page request. Instead I'd like to take the approach similar to Node Queue's concept of a "smart queue", where a single flag is set up (say a "wishlist" flag) that users are allowed to sub-categorize. All user-specific flags would probably live in a separate table with any user-specific settings.

I think it's likely that this functionality would take a significant amount of code to implement, since it will require UI changes, Views API extension, updates to the actions, rules, and token integrations, etc. If possible I'd like it to be a separate module from Flag core.

seehawk’s picture

Just curious to see if this functionality was going to be a part of the 2.0 module. Also, would an approach similar to the one suggested here http://drupal.org/node/625618 be a more lightweight approach that could be implemented more easily?

quicksketch’s picture

No, it's not part of 2.0, and as stated in #13, I'd prefer this were an add-on module rather than part of Flag, considering the amount of peripheral UI it would require.

seehawk’s picture

Makes sense. I'm not much of a Drupal coder yet, but I'd love to see this module become a reality. My skills are in IA and UI design, as well as project management. I'd be happy to pitch in with anyone who's interested in taking this on.

awolfey’s picture

It looks like I may have to scratch this itch for a project. Has anyone started or does anyone want to collaborate?

awolfey’s picture

Version: 6.x-1.x-dev » 6.x-2.0-beta2
Assigned: Unassigned » awolfey
Status: Active » Needs work
StatusFileSize
new7.33 KB

Attached is my first pass at a flag_custom module.

Notes:

- In no way should this be used in production yet!
- Flag 2 required.
- Access control not completely in place yet.
- Views support not there yet. I'd really like some help with this. (Without views, this is kind of pointless.)
- We need a hook_flag_delete so the flag_custom table can be cleaned up. I can provide a patch. (Is there one? I couldn't find it).
- We need a way to keep custom flags out of the main flag list. I could not see how to unset or hide the $flag object passed by reference in hook_flag_alter.
- I've really simplified the flag creation process. Basically you can set the title and that's it.
- There is a block where the current user can see his lists.
- Custom flags are only available on the node type where they were created. A story flag won't appear on blogs.

Questions for quicksketch:

- Should we continue this here, on a new issue, or should I create a project?
- Should we call it flag_custom? Private or personal also make some sense.

Feedback appreciated, especially help or pointers on views integration.

quicksketch’s picture

Wow awolfey this is pretty great! I think making a new project makes sense, this (as expected) is a sweeping set of functionality that makes sense to keep separate from Flag. There are a few code-style things here and there, but the larger concerns are these:

- There's no way to set the defaults for custom flags other than manually specifying options in settings.php or through variable_set(). Rather than hard-coding a site-wide default, it would make sense if you could make one "master" flag, then all the custom flags would use that Flag for all settings (except title).

- This module is going to have crazy performance problems if put into wide use. Flag currently loads *all* flags on *all* page loads. This makes sense the way Flag is intended to be used, most sites have less than 10 flags and more than one flag per page. However if you have thousands of flags, but only need to use 2-3 of them on each page, you're going to be spending a lot of time loading flags that aren't needed.

awolfey’s picture

I like the idea of a "master" flag. That will let us have masters for nodes, users, comments or even per node type. For now I've just hard coded the module for nodes, and the default flag settings are in the admin settings form.

flag_custom can have its own function to load its flags, but how will you prevent flag from loading all the custom flags?

Anyone have thoughts on the name before I create the project?

quicksketch’s picture

Somehow I missed the admin settings form (I only read the .module file), sorry about that.

I don't know how we should solve the performance problem. Flag wasn't meant to be used like this. Though if you have ideas we can implement them, though it'd be a shame to add a performance penalty by loading flags individually when most sites won't be used this add-on module.

As for a name, I was thinking "Flag lists", since it's like the user gets to make their own lists, though that implies you'll actually be making lists with the flagged content, which might not necessarily be the case.

awolfey’s picture

Could we wrap this in db_rewrite_sql() and then flag_custom could rewrite it to exclude its flags?

from flag_get_flags() in flag.module line 1304:

    // Database flags.
    $result = db_query("SELECT f.*, fn.type FROM {flags} f LEFT JOIN {flag_types} fn ON fn.fid = f.fid");

could become:

    // Database flags.
    $sql = "SELECT f.*, fn.type FROM {flags} f LEFT JOIN {flag_types} fn ON fn.fid = f.fid";
    db_rewrite_sql($sql, 'flags', 'fid');
    $result = db_query($sql);
quicksketch’s picture

That would be fine with me, though then you couldn't load your flags at all through flag_get_flag(), since the flags are only loaded once per request. Though perhaps you could load your own flags through hook_flag_default_flags()? I'm not sure and this certainly will require some more thought, and likely an API addition.

awolfey’s picture

That might work, or I could just load them another way. I'll try some things out next week. Thanks for you help.

seehawk’s picture

Awesome awolfey! I can't wait to start testing this out tonight!

To quicksketch's comment in #19 (and bearing in mind that I haven't had a chance to try out the module yet), would it make sense to have the administrator assign a maximum number of flags that each user can set up (for the sake of argument, 10), and then create 10 generic "buckets" that flags can go into (user_flag_1, user_flag_2, etc.)? Then, each user would be able to have a private name for each bucket, and those buckets would be set to allow each user to see only his/her own flags. (So, user X might call user_flag_1 "Favorites" and user Y might call user_flag_1 "My Content", but both lists would appear in the database as user_flag_1.

It's similar to the idea that I referenced in #14. Just a thought, but I wanted to throw it out there.

awolfey’s picture

Here's what I ended up doing in the rewrite: Instead of eliminating custom flags completely from flag_get_flags() all the time, I am narrowing the flag list to custom and regular flags that are available on the current content.

I thought that the flags would be cached, but it looked to me like the flag / unflag callback is rebuilding $flags, so I checked for that too.

I think this will ease the performance hit, and it segregates the custom flags to their own admin list.

<?php

/**
 * Implementation of hook_db_rewrite_sql().
 *
 * Alter the flag_get_flags() query so that it only inludes custom flags that are
 * owned by the current user and are available on the current content type, or
 * needed for the flag or unflag callback.
 */
function flag_custom_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
  if ($primary_table == 'flags' && $primary_field == 'fid') {
    $fids = implode(', ', flag_custom_get_content_fids());
    $return = array();
    $return['where'] = "f.fid IN ($fids)";
    return $return;
  }
}

/**
 * Helper function to build an array of all flags available to or owned by the
 * current user and that are available on the current content type.
 */
function flag_custom_get_content_fids() {
  global $user;
  
  // This is a node view. We only care about nodes for now.
  if (arg(0) == 'node' && is_numeric(arg(1)) && is_null(arg(2))) {
    $type = db_result(db_query("SELECT type from {node} WHERE nid = %d", arg(1)));
    
    // Get current user's flags for this node.
    $fc_result = db_query("SELECT f.fid
        FROM {flag_custom} fc
        LEFT JOIN {flag_types} fn ON fn.fid = fc.fid
        LEFT JOIN {flags} f ON fc.fid = f.fid
        WHERE fc.uid = %d
        AND fn.type = '%s'", $user->uid, $type);
    
    while ($row = db_fetch_array($fc_result)) {
      $fids[] = $row['fid'];
    }
  }
  
  // This is the flag / unflag callback
  elseif (arg(0) == 'flag' && (arg(1) == 'flag' || arg(1) == 'unflag')) {
    // Get the flag for this request.
    $fids[] = db_result(db_query("SELECT f.fid
        FROM {flags} f
        WHERE f.name = '%s'", arg(2)));
  }
  
  // Get the regular flags for this node. The flag module will narrow by role,
  // etc. when flag_get_flags() is called. These flags are always returned.
  $f_result = db_query("SELECT f.fid
        FROM {flags} f
        LEFT JOIN {flag_custom} fc ON fc.fid = f.fid
        WHERE fc.fid IS NULL");
  
  while ($row = db_fetch_array($f_result)) {
    $fids[] = $row['fid'];
  }
  return array_unique($fids);
}
?>
quicksketch’s picture

awolfey: If it looks like db_rewrite_sql() is going to do the job for you, let's open a new issue and file a separate patch for that. I'm not sure about arg() checking... seems like it's getting pretty far into the hacky territory. Then again, (as I've said a few times already) Flag wasn't really made to handle this situation at all so such approaches shouldn't be surprising if they are required.

awolfey’s picture

xmacinfo’s picture

Any progress about #18? Is there a new contrib module available or in the works?

awolfey’s picture

In fact, I'm picking this back up now. I hope to have something soon.

This will need quicksketch to accept the patch from 28 or offer another direction.

quicksketch’s picture

I'm fine with #750578: Patch creates hook_flag_delete() (the necessary patch for this functionality), but I'd like to see the add-on module working before making unnecessary changes to Flag. It may be that a lot more changes are necessary than just that one. I'm curious to see how much modification will be needed, since Flag wasn't made to handle this feature-set at all.

awolfey’s picture

I have the module working now. I will add it here as soon as I finish views integration.

drumm’s picture

Any update on this? Is the module at #882036: From 6.x-2.6, PHP code gets a blank page the most current? This might be useful for Drupal.org's upcoming dashboard feature.

drumm’s picture

mooffie’s picture

This might be useful for Drupal.org's upcoming dashboard feature.

Is this a D7 thing? If so, #871064: Making flaggings fieldable might be a better solution.

Any update on this? [...] hook_flag_delete()

I think it'd be better to wait till the first round of the #871064 patch because it deals with some of the same issues. E.g., deleting a flag should probably call flag_reset_flag(), which in turn triggers the hook.

quicksketch’s picture

Status: Needs work » Postponed

Is this a D7 thing?

Drupal.org will run D6 for the initial iteration. awolfey up the initial version of the module at http://drupal.org/project/flag_lists, though I'm still rather suspicious of the use of the flags table for user-defined flags. We can discuss any further progress over in that module's queue I think. I'm moving this to postponed until that module reaches a usable state.

quicksketch’s picture

Status: Postponed » Closed (won't fix)

A year later, I'm not sure if Flag Lists module will ever be totally usable, but at least it has a stable release (1.1). I think we're done enough here in the Flag queue. Please open a new issue for any individual enhancements that are needed in Flag.